Auto reload and bug fixes
This commit is contained in:
11
.idea/inspectionProfiles/Project_Default.xml
generated
11
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -2,5 +2,16 @@
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myValues">
|
||||
<value>
|
||||
<list size="2">
|
||||
<item index="0" class="java.lang.String" itemvalue="src" />
|
||||
<item index="1" class="java.lang.String" itemvalue="async" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myCustomValuesEnabled" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
131
package-lock.json
generated
131
package-lock.json
generated
@@ -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",
|
||||
|
||||
10
package.json
10
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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {getUserInfo} from './utils';
|
||||
import {getUserInfo} from './utils/utils';
|
||||
|
||||
export async function getUserName(): Promise<string> {
|
||||
const info = await getUserInfo();
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export function getConfig(): Promise<ClientConfig> {
|
||||
}
|
||||
|
||||
export async function getUserInfo(): Promise<UserInfo|undefined> {
|
||||
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();
|
||||
}
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
13
src/app.ts
13
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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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<UserInfo|undefined>(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();
|
||||
}
|
||||
};
|
||||
|
||||
58
src/utils/auto-reload.ts
Normal file
58
src/utils/auto-reload.ts
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -5,22 +5,22 @@ enum ResolvableState {
|
||||
DONE
|
||||
}
|
||||
|
||||
class FetchOnce<T> {
|
||||
class FetchOnce<T, U extends Array<unknown>> {
|
||||
protected data: T|undefined;
|
||||
protected error: unknown|undefined;
|
||||
protected state: ResolvableState = ResolvableState.WAITING;
|
||||
protected pendings: [(res: Promise<T>|T) => void, (reason: unknown) => void][] = [];
|
||||
|
||||
constructor(protected fetchMethod?: () => Promise<T>) { }
|
||||
constructor(protected fetchMethod?: (...args: U) => Promise<T>) { }
|
||||
|
||||
public resolve(): Promise<T> {
|
||||
public resolve(...args: U): Promise<T> {
|
||||
// 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<T> {
|
||||
}
|
||||
}
|
||||
|
||||
export class Resolvable<T> extends FetchOnce<T> {
|
||||
constructor(fetchMethod: () => Promise<T>) {
|
||||
export class Resolvable<T, U extends Array<unknown>> extends FetchOnce<T, U> {
|
||||
constructor(fetchMethod: (...args: U) => Promise<T>) {
|
||||
super(fetchMethod);
|
||||
}
|
||||
}
|
||||
|
||||
export class WaitForSync<T> extends FetchOnce<T> {
|
||||
export class WaitForSync<T, U extends Array<unknown>> extends FetchOnce<T, U> {
|
||||
protected state: ResolvableState = ResolvableState.PENDING;
|
||||
|
||||
constructor() {
|
||||
|
||||
2
src/utils/helpers/urlJoin.ts
Normal file
2
src/utils/helpers/urlJoin.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import * as properUrlJoin from 'proper-url-join';
|
||||
export const urlJoin = properUrlJoin as unknown as properUrlJoin.default;
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
5
src/utils/types/logging.d.ts
vendored
Normal file
5
src/utils/types/logging.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
declare namespace Express {
|
||||
interface Request {
|
||||
noLogging: boolean|undefined;
|
||||
}
|
||||
}
|
||||
@@ -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}'});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user