diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..476dc0f 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,16 @@ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3b2421e..44046d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -528,6 +528,15 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -715,6 +724,28 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "character-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", @@ -826,6 +857,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concurrently": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", + "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^6.1.0", + "tree-kill": "^1.2.2", + "yargs": "^13.3.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + } + } + }, "connect-redis": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-5.0.0.tgz", @@ -904,6 +981,12 @@ "assert-plus": "^1.0.0" } }, + "date-fns": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", + "integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1980,6 +2063,12 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "json-prune": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/json-prune/-/json-prune-1.1.0.tgz", @@ -2324,6 +2413,12 @@ "node-sass": "^4.3.0" } }, + "node-watch": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.0.tgz", + "integrity": "sha512-OOBiglke5SlRQT5WYfwXTmYqTfXjcTNBHpalyHLtLxDpQYVpVRkJqabcch1kmwJsjV/J4OZuzEafeb4soqtFZA==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -2929,6 +3024,15 @@ "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", "dev": true }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -3082,6 +3186,12 @@ "amdefine": ">=0.0.4" } }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -3232,6 +3342,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -3333,6 +3452,12 @@ "punycode": "^2.1.1" } }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -3667,6 +3792,12 @@ "mkdirp": "^0.5.1" } }, + "ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", + "dev": true + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index 1b1c6d7..9d502f4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "scripts": { "lint": "eslint . --ext .ts", "lint-fix": "eslint . --ext .ts --fix", - "debug": "tsc-watch --onSuccess \"node --enable-source-maps --use-openssl-ca --unhandled-rejections=strict ./out/index\"", + "update-client-hash": "node -e \"require('fs').writeFileSync('public/misc/hash.txt', require('randomstring').generate())\"", + "debug-client": "tsc-watch --project ./public/js-source", + "debug-server": "tsc-watch --onSuccess \"node --enable-source-maps --use-openssl-ca --unhandled-rejections=strict ./out/index\"", + "debug": "concurrently \"npm run debug-client\" \"npm run debug-server\"", "build": "tsc", "production": "node --use-openssl-ca --unhandled-rejections=strict ./out/index", "install-debug": "npm install && npm run build", @@ -41,10 +44,13 @@ "@types/uuid": "^8.3.0", "@typescript-eslint/eslint-plugin": "^4.7.0", "@typescript-eslint/parser": "^4.7.0", + "concurrently": "^5.3.0", "eslint": "^7.13.0", "eslint-plugin-no-null": "^1.0.2", "eslint-plugin-promise": "^4.2.1", + "node-watch": "^0.7.0", "tsc-watch": "^4.2.9", - "typescript": "^4.0.5" + "typescript": "^4.0.5", + "ws": "^7.4.0" } } diff --git a/public/js-source/.eslintrc.js b/public/js-source/.eslintrc.js index 5a8ae8a..401a44e 100644 --- a/public/js-source/.eslintrc.js +++ b/public/js-source/.eslintrc.js @@ -29,6 +29,8 @@ module.exports = { "no-void": "error", "comma-spacing": "error", "comma-dangle": ["error", "always-multiline"], + "comma-style": "error", + "semi": "error", "no-restricted-imports": ["error", "assert", "buffer", "child_process", "cluster", "crypto", "dgram", "dns", "domain", "events", "freelist", diff --git a/public/js-source/src/SomeModule.ts b/public/js-source/src/SomeModule.ts index 884d9de..48fdee2 100644 --- a/public/js-source/src/SomeModule.ts +++ b/public/js-source/src/SomeModule.ts @@ -1,4 +1,4 @@ -import {getUserInfo} from './utils'; +import {getUserInfo} from './utils/utils'; export async function getUserName(): Promise { const info = await getUserInfo(); diff --git a/public/js-source/src/index.ts b/public/js-source/src/index.ts index c4cef9a..6090cd0 100644 --- a/public/js-source/src/index.ts +++ b/public/js-source/src/index.ts @@ -1,7 +1,5 @@ -// Export setConfig so that the external url can set set automatically - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export {setConfig} from './utils'; +// Export setConfig so that the external url can set set automatically by the server +export {setConfig} from './utils/utils'; import {getUserName} from './SomeModule'; diff --git a/public/js-source/src/resolvable.ts b/public/js-source/src/utils/resolvable.ts similarity index 100% rename from public/js-source/src/resolvable.ts rename to public/js-source/src/utils/resolvable.ts diff --git a/public/js-source/src/types/userinfo.d.ts b/public/js-source/src/utils/types/userinfo.d.ts similarity index 100% rename from public/js-source/src/types/userinfo.d.ts rename to public/js-source/src/utils/types/userinfo.d.ts diff --git a/public/js-source/src/utils.ts b/public/js-source/src/utils/utils.ts similarity index 81% rename from public/js-source/src/utils.ts rename to public/js-source/src/utils/utils.ts index 58f6d97..3ec5ed0 100644 --- a/public/js-source/src/utils.ts +++ b/public/js-source/src/utils/utils.ts @@ -17,7 +17,7 @@ export function getConfig(): Promise { } export async function getUserInfo(): Promise { - const getBaseUrl = await getConfig(); - const res = await fetch(getBaseUrl.EXTERNAL_BASE_URL + "/api/user"); + const config = await getConfig(); + const res = await fetch(config.EXTERNAL_BASE_URL + "/api/user"); return res.json(); } diff --git a/src/.eslintrc.js b/src/.eslintrc.js index eb74958..2ce8160 100644 --- a/src/.eslintrc.js +++ b/src/.eslintrc.js @@ -11,6 +11,7 @@ module.exports = { 'eslint:recommended', "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", + "plugin:promise/recommended", ], rules: { "no-console": "error", @@ -30,16 +31,8 @@ module.exports = { "no-void": "error", "comma-spacing": "error", "comma-dangle": ["error", "always-multiline"], - "promise/no-return-wrap": "error", - "promise/param-names": "error", - "promise/catch-or-return": "error", - "promise/no-native": "off", - "promise/no-nesting": "warn", - "promise/no-promise-in-callback": "warn", - "promise/no-callback-in-promise": "warn", - "promise/avoid-new": "warn", - "promise/no-new-statics": "error", - "promise/no-return-in-finally": "warn", - "promise/valid-params": "warn", + "comma-style": "error", + "semi": "error", + "promise/always-return": "off", }, }; diff --git a/src/app.ts b/src/app.ts index 255c4ce..85777f3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -6,15 +6,18 @@ import * as redisStore from 'connect-redis'; import * as session from 'express-session'; import * as sassMiddleware from 'node-sass-middleware'; import indexRouter from './routes'; -import {HttpLogger, Redis, Config, setupAuthProxy} from './utils'; +import {HttpLogger, Redis, Config, setupAuthProxy, getReloadRouter} from './utils'; import {Store} from 'express-session'; - export const app = express(); // view engine setup app.set('views', path.join(__dirname, '../views')); app.set('view engine', 'pug'); +app.use((req, res, next) => { + res.locals.Config = Config; + next(); +}); const router = express.Router(); @@ -24,7 +27,9 @@ app.use(express.json()); app.use(express.urlencoded({extended: false})); // auth proxy middleware -app.use(setupAuthProxy); +router.use(setupAuthProxy); +// auto reloader (when running in debug mode) +router.use(getReloadRouter()); // session let sessionStore: Store|undefined = undefined; @@ -32,7 +37,7 @@ if (Redis.client) { const RedisStore = redisStore(session); sessionStore = new RedisStore({client: Redis.client}); } -app.use(session({ +router.use(session({ store: sessionStore, secret: Config.SESSION_SECRET, resave: false, diff --git a/src/index.ts b/src/index.ts index 3127e54..86bd82e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import {Config, Logger} from './utils'; app.set('port', Config.PORT); const server = http.createServer(app); -server.listen(Config.PORT); +app.listen(Config.PORT); server.on('error', onError); server.on('listening', onListening); diff --git a/src/routes/index.ts b/src/routes/index.ts index 5ca3f00..64f893b 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -12,7 +12,7 @@ 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, externalUrl: Config.EXTERNAL_BASE_URL}); + res.render('index', {title: 'Express', email}); }); router.get('/logout', (req, res) => { diff --git a/src/utils/auth-proxy.ts b/src/utils/auth-proxy.ts index 8a54a7f..95f01f4 100644 --- a/src/utils/auth-proxy.ts +++ b/src/utils/auth-proxy.ts @@ -2,11 +2,10 @@ import {Request, RequestHandler} from 'express'; import {Config, Logger} from '.'; import {Resolvable} from './helpers/resolvable'; import fetch from 'node-fetch'; -import * as properUrlJoin from 'proper-url-join'; -const urlJoin = properUrlJoin as unknown as properUrlJoin.default; +import {urlJoin} from './helpers/urlJoin'; export const setupAuthProxy: RequestHandler = (req: Request, res, next) => { - const resolvable = new Resolvable(async () => { + const resolvable = new Resolvable(async () => { if (!Config.USERINFO_HEADER) { return undefined; } @@ -17,7 +16,7 @@ export const setupAuthProxy: RequestHandler = (req: Request, res, next) => { } try { const res = await fetch(url, {headers: [[Config.USERINFO_HEADER, token]]}); - return await res.json(); + return await res.json() as UserInfo; } catch (e) { Logger.warn(e); return undefined; @@ -32,6 +31,6 @@ export const setupAuthProxy: RequestHandler = (req: Request, res, next) => { } this.redirect(307, url); return true; - } + }; next(); -} +}; diff --git a/src/utils/auto-reload.ts b/src/utils/auto-reload.ts new file mode 100644 index 0000000..4ea331b --- /dev/null +++ b/src/utils/auto-reload.ts @@ -0,0 +1,58 @@ +import {Router} from 'express'; +import {Config} from './config'; +import {Logger} from './logging'; +import {urlJoin} from './helpers/urlJoin'; +import {v4} from 'uuid'; +import Timeout = NodeJS.Timeout; + +export function getReloadRouter(): Router { + const reloadRouter = Router(); + if (!Config.isProduction) { + let uuid = v4(); + let updateTimeout: Timeout|undefined = undefined; + import("node-watch").then((watch) => { + watch.default('public', {recursive: true}, (evt, name) => { + if (updateTimeout !== undefined) clearTimeout(updateTimeout); + updateTimeout = setTimeout(() => { + uuid = v4(); + }, 200); + }); + }).catch((err) => { Logger.error(err); }); + + reloadRouter.get("/auto-reload/client.js", (req, res) => { + Logger.debug(req.url, req.originalUrl, req.baseUrl); + res.setHeader('Content-Type', "application/javascript"); + // language=JavaScript + res.send(` + const loc = window.location; + const url = loc.protocol+'//'+loc.host+'${urlJoin(req.baseUrl, "/auto-reload")}'; + const parse = async res => (await res.json()).uuid; + let hash = undefined; + let hadError = false; + setInterval(async () => { + try { + const data = await parse(await fetch(url)); + if (data) { + hash = hash === undefined ? data : hash; + if (hash !== data) { + window.location.reload(); + } + } + } catch (e) { + if (hadError === false) { + console.log(e); + hadError = true; + } + } + }, 3000); + `.replace(/\t/g, "")); + }); + + reloadRouter.get("/auto-reload", (req, res) => { + req.noLogging = true; + res.json({uuid}); + }); + } + + return reloadRouter; +} diff --git a/src/utils/config.ts b/src/utils/config.ts index 8dd3ffe..d396065 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -36,5 +36,7 @@ const envs = { export const Config = { ...envs, isProduction, - EXTERNAL_BASE_URL: envs.EXTERNAL_BASE_URL || urlJoin(`http://${envs.HOSTNAME}${envs.PORT !== 80 ? `:${envs.PORT}` : ""}`), + EXTERNAL_BASE_URL: + envs.EXTERNAL_BASE_URL || + urlJoin(`http://${envs.HOSTNAME}${envs.PORT !== 80 ? `:${envs.PORT}` : ""}`, envs.BASE_PATH), } diff --git a/src/utils/helpers/resolvable.ts b/src/utils/helpers/resolvable.ts index 5a99fb3..42a55bd 100644 --- a/src/utils/helpers/resolvable.ts +++ b/src/utils/helpers/resolvable.ts @@ -5,22 +5,22 @@ enum ResolvableState { DONE } -class FetchOnce { +class FetchOnce> { protected data: T|undefined; protected error: unknown|undefined; protected state: ResolvableState = ResolvableState.WAITING; protected pendings: [(res: Promise|T) => void, (reason: unknown) => void][] = []; - constructor(protected fetchMethod?: () => Promise) { } + constructor(protected fetchMethod?: (...args: U) => Promise) { } - public resolve(): Promise { + public resolve(...args: U): Promise { // eslint-disable-next-line promise/avoid-new return new Promise((resolve, reject) => { switch (this.state) { case ResolvableState.WAITING: this.state = ResolvableState.PENDING; this.pendings.push([resolve, reject]); - if (this.fetchMethod) this.parsePromise(this.fetchMethod()); + if (this.fetchMethod) this.parsePromise(this.fetchMethod(...args)); break; case ResolvableState.PENDING: this.pendings.push([resolve, reject]); @@ -52,13 +52,13 @@ class FetchOnce { } } -export class Resolvable extends FetchOnce { - constructor(fetchMethod: () => Promise) { +export class Resolvable> extends FetchOnce { + constructor(fetchMethod: (...args: U) => Promise) { super(fetchMethod); } } -export class WaitForSync extends FetchOnce { +export class WaitForSync> extends FetchOnce { protected state: ResolvableState = ResolvableState.PENDING; constructor() { diff --git a/src/utils/helpers/urlJoin.ts b/src/utils/helpers/urlJoin.ts new file mode 100644 index 0000000..0fc1991 --- /dev/null +++ b/src/utils/helpers/urlJoin.ts @@ -0,0 +1,2 @@ +import * as properUrlJoin from 'proper-url-join'; +export const urlJoin = properUrlJoin as unknown as properUrlJoin.default; diff --git a/src/utils/index.ts b/src/utils/index.ts index 8841858..ef022b5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,3 +2,5 @@ export {Config} from './config'; export {Redis} from './redis'; export {Logger, HttpLogger} from './logging'; export {setupAuthProxy} from './auth-proxy'; +export {Resolvable, WaitForSync} from './helpers/resolvable'; +export {getReloadRouter} from './auto-reload'; diff --git a/src/utils/logging.ts b/src/utils/logging.ts index 2282404..b2ad7c8 100644 --- a/src/utils/logging.ts +++ b/src/utils/logging.ts @@ -33,6 +33,7 @@ for (const level of levels) { export const HttpLogger: RequestHandler = (req, res, next) => { const start = Date.now(); + const path = req.path; type Callback = (() => void)|undefined; const end = res.end; res.end = function(...args: [Callback] & [unknown, Callback] & [unknown, BufferEncoding, Callback]) { @@ -45,8 +46,9 @@ export const HttpLogger: RequestHandler = (req, res, next) => { const status = colorFunction(res.statusCode.toString(10)); const method = req.method.toUpperCase().padEnd(6, " "); const responseTime = (Date.now()-start).toString(10).padStart(3, " "); - Logger.http(`${status} ${method} ${responseTime}ms ${req.path}`); + if (!req.noLogging) + Logger.http(`${status} ${method} ${responseTime}ms ${path}`); end.apply(res, args); }; next(); -} +}; diff --git a/src/utils/types/logging.d.ts b/src/utils/types/logging.d.ts new file mode 100644 index 0000000..83b2916 --- /dev/null +++ b/src/utils/types/logging.d.ts @@ -0,0 +1,5 @@ +declare namespace Express { + interface Request { + noLogging: boolean|undefined; + } +} diff --git a/views/layout.pug b/views/layout.pug index 2c5cdea..2f8e0e2 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -1,14 +1,16 @@ +- const baseUrl = Config.EXTERNAL_BASE_URL; doctype html html head title= title - link(rel='stylesheet', href='/styles/style.css') + link(rel='stylesheet', href=baseUrl+'/styles/style.css') + if !Config.isProduction + script(type='text/javascript', async, src=baseUrl+'/auto-reload/client.js') body block content - script(type='text/javascript', src='/js/require-2.3.6.min.js') - script(type='text/javascript', src='/js/bundle.js') + script(type='text/javascript', src=baseUrl+'/js/require-2.3.6.min.js') + script(type='text/javascript', src=baseUrl+'/js/bundle.js') script. require(['src/index'], function (index) { - console.log(index); - index.setConfig({EXTERNAL_BASE_URL: '#{externalUrl}'}); + index.setConfig({EXTERNAL_BASE_URL: '#{baseUrl}'}); });