Moved backend to a separate directory
This commit is contained in:
81
backend/src/app.ts
Normal file
81
backend/src/app.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import * as createError from 'http-errors';
|
||||
import * as express from 'express';
|
||||
import {NextFunction, Request, Response} from 'express';
|
||||
import * as path from 'path';
|
||||
import * as sassMiddleware from 'node-sass-middleware';
|
||||
import * as compression from 'compression';
|
||||
import indexRouter from './routes';
|
||||
import {AuthProxy, AutoReloader, DefaultConfig, HttpLogger, Polyfill, PermManager} from 'pkg-express-utils';
|
||||
|
||||
export const app = express();
|
||||
|
||||
// Permissions
|
||||
PermManager
|
||||
.grant('user')
|
||||
.execute('read').on('userinfo')
|
||||
.grant('coe_bs')
|
||||
.extend('user')
|
||||
.execute('write').on('userinfo');
|
||||
|
||||
// view engine setup
|
||||
app.set('views', path.join(__dirname, '../views'));
|
||||
app.set('view engine', 'pug');
|
||||
app.use((req, res, next) => {
|
||||
res.locals.DefaultConfig = DefaultConfig;
|
||||
next();
|
||||
});
|
||||
|
||||
// http logger
|
||||
app.use(HttpLogger);
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({extended: false}));
|
||||
|
||||
// compression
|
||||
app.use(compression());
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// auth proxy middleware
|
||||
router.use(AuthProxy.router);
|
||||
// auto reloader (when running in debug mode)
|
||||
router.use(AutoReloader.getRouter({
|
||||
frontendDirs: './public',
|
||||
}));
|
||||
|
||||
// session
|
||||
//router.use(Session.getRouter());
|
||||
|
||||
// static config
|
||||
router.use('/js/polyfill.js', Polyfill.getRouter('./public/js/bundle.js'));
|
||||
router.use(sassMiddleware({
|
||||
src: path.join(__dirname, '../../public'),
|
||||
dest: path.join(__dirname, '../../public'),
|
||||
indentedSyntax: true, // true = .sass and false = .scss
|
||||
sourceMap: true,
|
||||
}));
|
||||
router.use(express.static(path.join(__dirname, '../../public')));
|
||||
|
||||
router.use(indexRouter);
|
||||
app.use(DefaultConfig.BASE_PATH, router);
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use((req, res, next) => {
|
||||
next(createError(404));
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use((err: Error&{status?: number}, req: Request, res: Response, next: NextFunction) => {
|
||||
if (res.headersSent) {
|
||||
return next(err);
|
||||
}
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = !DefaultConfig.isProduction ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('error');
|
||||
return undefined;
|
||||
});
|
||||
|
||||
|
||||
21
backend/src/healthcheck.ts
Normal file
21
backend/src/healthcheck.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/* eslint-disable no-process-exit,no-console */
|
||||
import * as http from 'http';
|
||||
import {DefaultConfig, urlJoin} from 'pkg-express-utils';
|
||||
|
||||
const options = {
|
||||
host: DefaultConfig.HOSTNAME,
|
||||
port: DefaultConfig.PORT,
|
||||
path: urlJoin(DefaultConfig.BASE_PATH, '/health'),
|
||||
timeout: 2000,
|
||||
};
|
||||
|
||||
const healthCheck = http.request(options, (res) => {
|
||||
process.exit(res.statusCode == 200 ? 0 : 1);
|
||||
});
|
||||
|
||||
healthCheck.on('error', (err) => {
|
||||
console.error('HEALTHCHECK ERROR', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
healthCheck.end();
|
||||
42
backend/src/index.ts
Normal file
42
backend/src/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint-disable no-process-exit */
|
||||
|
||||
import * as http from 'http';
|
||||
import {app} from './app';
|
||||
import {HttpError} from 'http-errors';
|
||||
import {DefaultConfig, Logger} from 'pkg-express-utils';
|
||||
|
||||
app.set('port', DefaultConfig.PORT);
|
||||
const server = http.createServer(app);
|
||||
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
server.listen(DefaultConfig.PORT);
|
||||
|
||||
function onError(error: HttpError): void {
|
||||
if (error.syscall !== 'listen') {
|
||||
Logger.error(error);
|
||||
}
|
||||
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
Logger.error(DefaultConfig.PORT + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
Logger.error(DefaultConfig.PORT + ' is already in use');
|
||||
process.exit(2);
|
||||
break;
|
||||
default:
|
||||
Logger.error(error);
|
||||
process.exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
function onListening(): void {
|
||||
const addr = server.address();
|
||||
const bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + (addr ?? {port: undefined}).port;
|
||||
Logger.debug('Listening on ' + bind);
|
||||
}
|
||||
11
backend/src/routes/api/user.ts
Normal file
11
backend/src/routes/api/user.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import * as express from 'express';
|
||||
import {PermManager} from 'pkg-express-utils';
|
||||
|
||||
const userRouter = express.Router();
|
||||
|
||||
/* GET user info. */
|
||||
userRouter.get('/', PermManager.getRouter('userinfo', {action: 'read'}), async (req, res) => {
|
||||
res.json(await req.getUserInfo() || {});
|
||||
});
|
||||
|
||||
export default userRouter;
|
||||
10
backend/src/routes/healthcheck.ts
Normal file
10
backend/src/routes/healthcheck.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import * as express from 'express';
|
||||
|
||||
const healthRouter = express.Router();
|
||||
|
||||
healthRouter.get('/', async (req, res) => {
|
||||
req.noHttpLogging = true;
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
export default healthRouter;
|
||||
19
backend/src/routes/index.ts
Normal file
19
backend/src/routes/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as express from 'express';
|
||||
import userRouter from './api/user';
|
||||
import healthRouter from './healthcheck';
|
||||
|
||||
const router = express.Router();
|
||||
export default router;
|
||||
|
||||
router.use('/api/user', userRouter);
|
||||
router.use('/health', healthRouter);
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', async (req, res) => {
|
||||
const email = (await req.getUserInfo())?.email ?? 'No email found!';
|
||||
res.render('index', {title: 'Express', email});
|
||||
});
|
||||
|
||||
router.get('/logout', (req, res) => {
|
||||
res.initLogout();
|
||||
});
|
||||
23
backend/src/types/extend-request.d.ts
vendored
Normal file
23
backend/src/types/extend-request.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// extend-request.d.ts
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
// fetch user info (needs AuthProxy and some headers)
|
||||
getUserInfo(): Promise<import('pkg-express-utils').UserInfo|undefined>;
|
||||
// fetch user info (needed for HttpLogger)
|
||||
noHttpLogging: boolean|undefined;
|
||||
// permission details (after a Permission route)
|
||||
permissionDetails: import('role-acl').Permission;
|
||||
// switch session to another user;does not close old session (after Session router)
|
||||
setSessionById(sessionId: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
interface Response {
|
||||
// initialize a logout (needs AuthProxy and some headers)
|
||||
initLogout(): boolean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
Reference in New Issue
Block a user