@naturalcycles/backend-lib 2.73.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin.mw.d.ts +4 -4
- package/dist/admin/base.admin.service.d.ts +11 -12
- package/dist/db/httpDBRequestHandler.d.ts +2 -2
- package/dist/deploy/deployPrepare.js +1 -0
- package/dist/index.d.ts +25 -24
- package/dist/index.js +28 -50
- package/dist/sentry/sentry.shared.service.d.ts +3 -3
- package/dist/server/appEngineLogMiddleware.d.ts +13 -0
- package/dist/server/{handlers/createGaeLogMiddleware.js → appEngineLogMiddleware.js} +4 -4
- package/dist/server/{handlers/asyncLocalStorage.mw.d.ts → asyncLocalStorageMiddleware.d.ts} +4 -4
- package/dist/server/{handlers/asyncLocalStorage.mw.js → asyncLocalStorageMiddleware.js} +5 -5
- package/dist/server/{handlers/bodyParserTimeout.mw.d.ts → bodyParserTimeoutMiddleware.d.ts} +4 -4
- package/dist/server/{handlers/bodyParserTimeout.mw.js → bodyParserTimeoutMiddleware.js} +10 -7
- package/dist/server/catchWrapper.d.ts +2 -2
- package/dist/server/createDefaultApp.d.ts +2 -2
- package/dist/server/createDefaultApp.js +13 -13
- package/dist/server/createDefaultApp.model.d.ts +8 -8
- package/dist/server/deployInfo.util.d.ts +2 -2
- package/dist/server/genericErrorMiddleware.d.ts +12 -0
- package/dist/server/{handlers/genericErrorHandler.mw.js → genericErrorMiddleware.js} +20 -8
- package/dist/server/getDefaultRouter.d.ts +2 -2
- package/dist/server/methodOverrideMiddleware.d.ts +8 -0
- package/dist/server/{handlers/methodOverride.mw.js → methodOverrideMiddleware.js} +3 -3
- package/dist/server/notFoundMiddleware.d.ts +2 -0
- package/dist/server/notFoundMiddleware.js +10 -0
- package/dist/server/okMiddleware.d.ts +2 -0
- package/dist/server/{handlers/okHandler.mw.js → okMiddleware.js} +3 -3
- package/dist/server/{handlers/reqValidation.mw.d.ts → reqValidationMiddleware.d.ts} +2 -2
- package/dist/server/{handlers/reqValidation.mw.js → reqValidationMiddleware.js} +0 -0
- package/dist/server/request.log.util.d.ts +2 -2
- package/dist/server/request.util.d.ts +10 -2
- package/dist/server/request.util.js +8 -0
- package/dist/server/requestTimeoutMiddleware.d.ts +31 -0
- package/dist/server/requestTimeoutMiddleware.js +68 -0
- package/dist/server/{handlers/safeJsonMiddleware.d.ts → safeJsonMiddleware.d.ts} +2 -2
- package/dist/server/{handlers/safeJsonMiddleware.js → safeJsonMiddleware.js} +0 -0
- package/dist/server/server.model.d.ts +37 -0
- package/dist/server/server.model.js +2 -0
- package/dist/server/serverStatsMiddleware.d.ts +13 -0
- package/dist/server/{handlers/serverStatsMiddleware.js → serverStatsMiddleware.js} +2 -2
- package/dist/server/serverStatusMiddleware.d.ts +3 -0
- package/dist/server/{handlers/statusHandler.js → serverStatusMiddleware.js} +7 -7
- package/dist/server/simpleRequestLoggerMiddleware.d.ts +12 -0
- package/dist/server/{handlers/simpleRequestLogger.mw.js → simpleRequestLoggerMiddleware.js} +5 -5
- package/dist/server/startServer.model.d.ts +2 -2
- package/dist/server/{handlers/validate.mw.d.ts → validateMiddleware.d.ts} +5 -5
- package/dist/server/{handlers/validate.mw.js → validateMiddleware.js} +0 -0
- package/dist/testing/express.test.service.d.ts +6 -6
- package/dist/testing/express.test.service.js +8 -5
- package/package.json +1 -2
- package/src/admin/admin.mw.ts +7 -4
- package/src/admin/base.admin.service.ts +11 -12
- package/src/admin/secureHeader.mw.ts +2 -2
- package/src/db/httpDBRequestHandler.ts +2 -3
- package/src/deploy/deployPrepare.ts +1 -0
- package/src/index.ts +54 -68
- package/src/sentry/sentry.shared.service.ts +3 -4
- package/src/server/{handlers/createGaeLogMiddleware.ts → appEngineLogMiddleware.ts} +4 -25
- package/src/server/{handlers/asyncLocalStorage.mw.ts → asyncLocalStorageMiddleware.ts} +5 -5
- package/src/server/{handlers/bodyParserTimeout.mw.ts → bodyParserTimeoutMiddleware.ts} +14 -13
- package/src/server/catchWrapper.ts +2 -2
- package/src/server/createDefaultApp.model.ts +8 -8
- package/src/server/createDefaultApp.ts +22 -19
- package/src/server/deployInfo.util.ts +1 -1
- package/src/server/{handlers/genericErrorHandler.mw.ts → genericErrorMiddleware.ts} +24 -14
- package/src/server/getDefaultRouter.ts +2 -2
- package/src/server/{handlers/methodOverride.mw.ts → methodOverrideMiddleware.ts} +5 -3
- package/src/server/notFoundMiddleware.ts +8 -0
- package/src/server/okMiddleware.ts +7 -0
- package/src/server/{handlers/reqValidation.mw.ts → reqValidationMiddleware.ts} +2 -2
- package/src/server/request.log.util.ts +2 -2
- package/src/server/request.util.ts +10 -2
- package/src/server/requestTimeoutMiddleware.ts +117 -0
- package/src/server/{handlers/safeJsonMiddleware.ts → safeJsonMiddleware.ts} +3 -3
- package/src/server/server.model.ts +56 -0
- package/src/server/{handlers/serverStatsMiddleware.ts → serverStatsMiddleware.ts} +4 -5
- package/src/server/{handlers/statusHandler.ts → serverStatusMiddleware.ts} +5 -5
- package/src/server/{handlers/simpleRequestLogger.mw.ts → simpleRequestLoggerMiddleware.ts} +8 -7
- package/src/server/startServer.model.ts +2 -2
- package/src/server/{handlers/validate.mw.ts → validateMiddleware.ts} +6 -6
- package/src/testing/express.test.service.ts +12 -8
- package/dist/server/handlers/createGaeLogMiddleware.d.ts +0 -30
- package/dist/server/handlers/genericErrorHandler.mw.d.ts +0 -13
- package/dist/server/handlers/methodOverride.mw.d.ts +0 -8
- package/dist/server/handlers/notFoundHandler.mw.d.ts +0 -2
- package/dist/server/handlers/notFoundHandler.mw.js +0 -9
- package/dist/server/handlers/okHandler.mw.d.ts +0 -2
- package/dist/server/handlers/requestTimeout.mw.d.ts +0 -16
- package/dist/server/handlers/requestTimeout.mw.js +0 -34
- package/dist/server/handlers/sentryErrorHandler.mw.d.ts +0 -10
- package/dist/server/handlers/sentryErrorHandler.mw.js +0 -26
- package/dist/server/handlers/serverStatsMiddleware.d.ts +0 -13
- package/dist/server/handlers/simpleRequestLogger.mw.d.ts +0 -12
- package/dist/server/handlers/statusHandler.d.ts +0 -3
- package/src/server/handlers/notFoundHandler.mw.ts +0 -7
- package/src/server/handlers/okHandler.mw.ts +0 -7
- package/src/server/handlers/requestTimeout.mw.ts +0 -62
- package/src/server/handlers/sentryErrorHandler.mw.ts +0 -34
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.respondWithError = exports.
|
|
3
|
+
exports.respondWithError = exports.genericErrorMiddleware = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const { APP_ENV } = process.env;
|
|
@@ -12,7 +12,7 @@ let sentryService;
|
|
|
12
12
|
* Returns HTTP code based on err.data.httpStatusCode (default to 500).
|
|
13
13
|
* Sends json payload as ErrorResponse, transformed via errorSharedUtil.
|
|
14
14
|
*/
|
|
15
|
-
function
|
|
15
|
+
function genericErrorMiddleware(cfg = {}) {
|
|
16
16
|
sentryService || (sentryService = cfg.sentryService);
|
|
17
17
|
return (err, req, res, _next) => {
|
|
18
18
|
// if (res.headersSent) {
|
|
@@ -29,14 +29,19 @@ function genericErrorHandler(cfg = {}) {
|
|
|
29
29
|
respondWithError(req, res, err);
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
exports.
|
|
32
|
+
exports.genericErrorMiddleware = genericErrorMiddleware;
|
|
33
33
|
// export interface ResponseWithError extends Response {
|
|
34
34
|
// __err?: any
|
|
35
35
|
// }
|
|
36
36
|
function respondWithError(req, res, err) {
|
|
37
37
|
var _a, _b;
|
|
38
38
|
const { headersSent } = res;
|
|
39
|
-
|
|
39
|
+
if (headersSent) {
|
|
40
|
+
req.error(`after headersSent`, err);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
req.error(err);
|
|
44
|
+
}
|
|
40
45
|
const originalError = (0, js_lib_1._anyToError)(err, Error, {
|
|
41
46
|
stringifyFn: nodejs_lib_1.inspectAnyStringifyFn,
|
|
42
47
|
});
|
|
@@ -58,8 +63,15 @@ function respondWithError(req, res, err) {
|
|
|
58
63
|
}
|
|
59
64
|
exports.respondWithError = respondWithError;
|
|
60
65
|
function shouldReportToSentry(err) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
const e = err;
|
|
67
|
+
// By default - report
|
|
68
|
+
if (!e?.data)
|
|
69
|
+
return true;
|
|
70
|
+
// If `report` is set - do as it says
|
|
71
|
+
if (e.data.report === true)
|
|
72
|
+
return true;
|
|
73
|
+
if (e.data.report === false)
|
|
74
|
+
return false;
|
|
75
|
+
// Report if http 5xx, otherwise not
|
|
76
|
+
return !e.data.httpStatusCode || e.data.httpStatusCode >= 500;
|
|
65
77
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BackendRequestHandler, BackendRouter } from './server.model';
|
|
2
2
|
/**
|
|
3
3
|
* Convenience method.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getDefaultRouter(defaultHandlers?:
|
|
5
|
+
export declare function getDefaultRouter(defaultHandlers?: BackendRequestHandler[]): BackendRouter;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BackendRequestHandler } from './server.model';
|
|
2
|
+
export interface MethodOverrideMiddlewareCfg {
|
|
3
|
+
/**
|
|
4
|
+
* @default _method
|
|
5
|
+
*/
|
|
6
|
+
methodKey?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function methodOverrideMiddleware(cfg?: MethodOverrideMiddlewareCfg): BackendRequestHandler;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
function
|
|
3
|
+
exports.methodOverrideMiddleware = void 0;
|
|
4
|
+
function methodOverrideMiddleware(cfg = {}) {
|
|
5
5
|
const { methodKey } = {
|
|
6
6
|
methodKey: '_method',
|
|
7
7
|
...cfg,
|
|
@@ -14,4 +14,4 @@ function methodOverride(cfg = {}) {
|
|
|
14
14
|
next();
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
|
-
exports.
|
|
17
|
+
exports.methodOverrideMiddleware = methodOverrideMiddleware;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.notFoundMiddleware = void 0;
|
|
4
|
+
const request_util_1 = require("./request.util");
|
|
5
|
+
function notFoundMiddleware() {
|
|
6
|
+
return (req, res) => {
|
|
7
|
+
res.status(404).send(`404 Not Found: ${(0, request_util_1.getRequestEndpoint)(req)}`);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
exports.notFoundMiddleware = notFoundMiddleware;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
function
|
|
3
|
+
exports.okMiddleware = void 0;
|
|
4
|
+
function okMiddleware() {
|
|
5
5
|
return (req, res) => {
|
|
6
6
|
res.json({ ok: 1 });
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
exports.
|
|
9
|
+
exports.okMiddleware = okMiddleware;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AnySchema, JoiValidationError } from '@naturalcycles/nodejs-lib';
|
|
2
|
-
import {
|
|
2
|
+
import { BackendRequestHandler } from './server.model';
|
|
3
3
|
export interface ReqValidationOptions<ERR extends Error> {
|
|
4
4
|
/**
|
|
5
5
|
* Pass a 'dot-paths' (e.g `pw`, or `input.pw`) that needs to be redacted from the output, in case of error.
|
|
@@ -12,4 +12,4 @@ export interface ReqValidationOptions<ERR extends Error> {
|
|
|
12
12
|
*/
|
|
13
13
|
report?: boolean | ((err: ERR) => boolean);
|
|
14
14
|
}
|
|
15
|
-
export declare function reqValidation(reqProperty: 'body' | 'params' | 'query', schema: AnySchema, opt?: ReqValidationOptions<JoiValidationError>):
|
|
15
|
+
export declare function reqValidation(reqProperty: 'body' | 'params' | 'query', schema: AnySchema, opt?: ReqValidationOptions<JoiValidationError>): BackendRequestHandler;
|
|
File without changes
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function logRequest(req:
|
|
1
|
+
import { BackendRequest } from './server.model';
|
|
2
|
+
export declare function logRequest(req: BackendRequest, statusCode: number, ...tokens: any[]): void;
|
|
3
3
|
export declare function coloredHttpCode(statusCode: number): string;
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { BackendRequest } from './server.model';
|
|
2
|
+
/**
|
|
3
|
+
* Returns e.g:
|
|
4
|
+
*
|
|
5
|
+
* GET /some/endpoint
|
|
6
|
+
*
|
|
7
|
+
* Gets the correct full path when used from sub-router-resources.
|
|
8
|
+
* Strips away the queryString.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getRequestEndpoint(req: BackendRequest): string;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getRequestEndpoint = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Returns e.g:
|
|
6
|
+
*
|
|
7
|
+
* GET /some/endpoint
|
|
8
|
+
*
|
|
9
|
+
* Gets the correct full path when used from sub-router-resources.
|
|
10
|
+
* Strips away the queryString.
|
|
11
|
+
*/
|
|
4
12
|
function getRequestEndpoint(req) {
|
|
5
13
|
let path = (req.baseUrl + (req.route?.path || req.path)).toLowerCase();
|
|
6
14
|
if (path.length > 1 && path.endsWith('/')) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BackendRequest, BackendRequestHandler, BackendResponse } from '../index';
|
|
2
|
+
export interface RequestTimeoutMiddlewareCfg {
|
|
3
|
+
/**
|
|
4
|
+
* @default 120
|
|
5
|
+
*/
|
|
6
|
+
timeoutSeconds?: number;
|
|
7
|
+
/**
|
|
8
|
+
* @default 503
|
|
9
|
+
*/
|
|
10
|
+
httpStatusCode?: number;
|
|
11
|
+
/**
|
|
12
|
+
* @default 'Request timed out'
|
|
13
|
+
*/
|
|
14
|
+
httpErrorMessage?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function requestTimeoutMiddleware(cfg?: RequestTimeoutMiddlewareCfg): BackendRequestHandler;
|
|
17
|
+
export interface CustomRequestTimeoutMiddlewareCfg {
|
|
18
|
+
/**
|
|
19
|
+
* @default 120
|
|
20
|
+
*/
|
|
21
|
+
timeoutSeconds?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Example:
|
|
25
|
+
*
|
|
26
|
+
* router.get('/', customRequestTimeoutMiddleware(
|
|
27
|
+
* (req, res) => res.status(409).send('my custom message!'),
|
|
28
|
+
* { timeoutSeconds: 30 },
|
|
29
|
+
* )
|
|
30
|
+
*/
|
|
31
|
+
export declare function customRequestTimeoutMiddleware(onTimeout: (req: BackendRequest, res: BackendResponse) => void | Promise<void>, cfg: CustomRequestTimeoutMiddlewareCfg): BackendRequestHandler;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.customRequestTimeoutMiddleware = exports.requestTimeoutMiddleware = void 0;
|
|
4
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
const code = 'REQUEST_TIMEOUT';
|
|
7
|
+
const REQUEST_TIMEOUT_QUERY_KEY = 'requestTimeout';
|
|
8
|
+
function requestTimeoutMiddleware(cfg = {}) {
|
|
9
|
+
const { timeoutSeconds: defTimeoutSeconds, httpStatusCode, httpErrorMessage, } = {
|
|
10
|
+
// Considerations about the default value of the timeout.
|
|
11
|
+
// Ideally the default value here would be HIGHER than the default timeout for getGot (in nodejs-lib),
|
|
12
|
+
// so, cross-service communication has a chance to fail SOONER than server times out,
|
|
13
|
+
// so, proper error from exact service is shown, rather than generic "503 request timed out"
|
|
14
|
+
timeoutSeconds: 120,
|
|
15
|
+
httpStatusCode: 503,
|
|
16
|
+
httpErrorMessage: 'Request timed out',
|
|
17
|
+
...cfg,
|
|
18
|
+
};
|
|
19
|
+
return function requestTimeoutHandler(req, res, next) {
|
|
20
|
+
const timeoutSeconds = req.query[REQUEST_TIMEOUT_QUERY_KEY]
|
|
21
|
+
? Number.parseInt(req.query[REQUEST_TIMEOUT_QUERY_KEY])
|
|
22
|
+
: defTimeoutSeconds;
|
|
23
|
+
// If requestTimeout was previously set - cancel it first
|
|
24
|
+
// Then set the new requestTimeout and handler
|
|
25
|
+
if (req.requestTimeout)
|
|
26
|
+
clearTimeout(req.requestTimeout);
|
|
27
|
+
req.requestTimeout = setTimeout(() => {
|
|
28
|
+
const endpoint = (0, index_1.getRequestEndpoint)(req);
|
|
29
|
+
const msg = `${httpErrorMessage} on ${endpoint} after ${(0, js_lib_1._ms)(timeoutSeconds * 1000)}`;
|
|
30
|
+
(0, index_1.respondWithError)(req, res, new js_lib_1.HttpError(msg, {
|
|
31
|
+
code,
|
|
32
|
+
httpStatusCode,
|
|
33
|
+
endpoint,
|
|
34
|
+
timeoutSeconds,
|
|
35
|
+
// userFriendly: true, // no, cause this error is not expected
|
|
36
|
+
}));
|
|
37
|
+
}, timeoutSeconds * 1000);
|
|
38
|
+
(0, index_1.onFinished)(res, () => clearTimeout(req.requestTimeout));
|
|
39
|
+
next();
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
exports.requestTimeoutMiddleware = requestTimeoutMiddleware;
|
|
43
|
+
/**
|
|
44
|
+
* Example:
|
|
45
|
+
*
|
|
46
|
+
* router.get('/', customRequestTimeoutMiddleware(
|
|
47
|
+
* (req, res) => res.status(409).send('my custom message!'),
|
|
48
|
+
* { timeoutSeconds: 30 },
|
|
49
|
+
* )
|
|
50
|
+
*/
|
|
51
|
+
function customRequestTimeoutMiddleware(onTimeout, cfg) {
|
|
52
|
+
const { timeoutSeconds = 120 } = cfg;
|
|
53
|
+
return function customRequestTimeoutHandler(req, res, next) {
|
|
54
|
+
if (req.requestTimeout)
|
|
55
|
+
clearTimeout(req.requestTimeout);
|
|
56
|
+
req.requestTimeout = setTimeout(async () => {
|
|
57
|
+
try {
|
|
58
|
+
await onTimeout(req, res);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
next(err);
|
|
62
|
+
}
|
|
63
|
+
}, timeoutSeconds * 1000);
|
|
64
|
+
(0, index_1.onFinished)(res, () => clearTimeout(req.requestTimeout));
|
|
65
|
+
next();
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.customRequestTimeoutMiddleware = customRequestTimeoutMiddleware;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BackendRequestHandler } from './server.model';
|
|
2
2
|
/**
|
|
3
3
|
* Replaces express's built-in req.json() function with the safe one,
|
|
4
4
|
* protected from circular references.
|
|
5
5
|
*
|
|
6
6
|
* Original: https://github.com/expressjs/express/blob/master/lib/response.js
|
|
7
7
|
*/
|
|
8
|
-
export declare function safeJsonMiddleware():
|
|
8
|
+
export declare function safeJsonMiddleware(): BackendRequestHandler;
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { CommonLogFunction } from '@naturalcycles/js-lib';
|
|
3
|
+
import { IRouter, Request, NextFunction, Response, Application } from 'express';
|
|
4
|
+
/**
|
|
5
|
+
* Use this interface instead of express.Request in cases when TypeScript gives an error, because it haven't "included" this very file.
|
|
6
|
+
*
|
|
7
|
+
* It's named like this to avoid clashes with other names.
|
|
8
|
+
* `BackendRequest` seems to not conflict with anything right now.
|
|
9
|
+
* Previous name `ExpressRequest` was clashing with Sentry.
|
|
10
|
+
*/
|
|
11
|
+
export interface BackendRequest extends Request {
|
|
12
|
+
log: CommonLogFunction;
|
|
13
|
+
warn: CommonLogFunction;
|
|
14
|
+
error: CommonLogFunction;
|
|
15
|
+
requestId?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Set by requestTimeoutMiddleware.
|
|
18
|
+
* Can be used to cancel/override the timeout.
|
|
19
|
+
*/
|
|
20
|
+
requestTimeout?: NodeJS.Timeout;
|
|
21
|
+
bodyParserTimeout?: NodeJS.Timeout;
|
|
22
|
+
}
|
|
23
|
+
export declare type BackendResponse = Response;
|
|
24
|
+
export declare type BackendRequestHandler = (req: BackendRequest, res: BackendResponse, next: NextFunction) => void;
|
|
25
|
+
export declare type BackendErrorRequestHandler = (err: any, req: BackendRequest, res: BackendResponse, next: NextFunction) => void;
|
|
26
|
+
export declare type BackendRouter = IRouter;
|
|
27
|
+
export declare type BackendApplication = Application;
|
|
28
|
+
declare module 'http' {
|
|
29
|
+
interface IncomingMessage {
|
|
30
|
+
log: CommonLogFunction;
|
|
31
|
+
warn: CommonLogFunction;
|
|
32
|
+
error: CommonLogFunction;
|
|
33
|
+
requestId?: string;
|
|
34
|
+
requestTimeout?: NodeJS.Timeout;
|
|
35
|
+
bodyParserTimeout?: NodeJS.Timeout;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BackendRequestHandler } from '../index';
|
|
2
|
+
/**
|
|
3
|
+
* Depends on serverStatsMiddleware to work.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
*
|
|
7
|
+
* router.get('/stats', serverStatsHTMLHandler)
|
|
8
|
+
*/
|
|
9
|
+
export declare const serverStatsHTMLHandler: BackendRequestHandler;
|
|
10
|
+
/**
|
|
11
|
+
* Unlocks serverStatsHTMLHandler
|
|
12
|
+
*/
|
|
13
|
+
export declare function serverStatsMiddleware(): BackendRequestHandler;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.serverStatsMiddleware = exports.serverStatsHTMLHandler = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const index_1 = require("
|
|
6
|
-
const request_util_1 = require("
|
|
5
|
+
const index_1 = require("../index");
|
|
6
|
+
const request_util_1 = require("./request.util");
|
|
7
7
|
const { GAE_INSTANCE } = process.env;
|
|
8
8
|
const serverStatsMap = {};
|
|
9
9
|
const percentiles = [50, 90, 99];
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getServerStatusData = exports.serverStatusMiddleware = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const time_lib_1 = require("@naturalcycles/time-lib");
|
|
7
|
-
const deployInfo_util_1 = require("
|
|
7
|
+
const deployInfo_util_1 = require("./deployInfo.util");
|
|
8
8
|
const { versions } = process;
|
|
9
9
|
const { GAE_APPLICATION, GAE_SERVICE, GAE_VERSION, APP_ENV } = process.env;
|
|
10
|
-
function
|
|
10
|
+
function serverStatusMiddleware(projectDir, extra) {
|
|
11
11
|
return async (req, res) => {
|
|
12
|
-
res.json(
|
|
12
|
+
res.json(getServerStatusData(projectDir, extra));
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
exports.
|
|
16
|
-
function
|
|
15
|
+
exports.serverStatusMiddleware = serverStatusMiddleware;
|
|
16
|
+
function getServerStatusData(projectDir = process.cwd(), extra) {
|
|
17
17
|
const { gitRev, gitBranch, prod, ts } = (0, deployInfo_util_1.getDeployInfo)(projectDir);
|
|
18
18
|
const deployBuildTimeUTC = time_lib_1.dayjs.unix(ts).toPretty();
|
|
19
19
|
const buildInfo = [time_lib_1.dayjs.unix(ts).toCompactTime(), gitBranch, gitRev].filter(Boolean).join('_');
|
|
@@ -33,7 +33,7 @@ function statusHandlerData(projectDir = process.cwd(), extra) {
|
|
|
33
33
|
...extra,
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
exports.
|
|
36
|
+
exports.getServerStatusData = getServerStatusData;
|
|
37
37
|
function getStartedStr() {
|
|
38
38
|
const serverStarted = time_lib_1.dayjs.utc().subtract(process.uptime(), 's');
|
|
39
39
|
const s1 = (0, time_lib_1.dayjs)(serverStarted).toPretty();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BackendRequestHandler } from '../index';
|
|
2
|
+
export interface SimpleRequestLoggerMiddlewareCfg {
|
|
3
|
+
/**
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
logStart: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
logFinish: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function simpleRequestLoggerMiddleware(_cfg?: Partial<SimpleRequestLoggerMiddlewareCfg>): BackendRequestHandler;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.simpleRequestLoggerMiddleware = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
6
|
-
const index_1 = require("
|
|
7
|
-
const request_log_util_1 = require("
|
|
6
|
+
const index_1 = require("../index");
|
|
7
|
+
const request_log_util_1 = require("./request.log.util");
|
|
8
8
|
const { APP_ENV } = process.env;
|
|
9
|
-
function
|
|
9
|
+
function simpleRequestLoggerMiddleware(_cfg = {}) {
|
|
10
10
|
// Disable logger in AppEngine, as it doesn't make sense there
|
|
11
11
|
// UPD: Only log in dev environment
|
|
12
12
|
if (APP_ENV !== 'dev')
|
|
@@ -36,4 +36,4 @@ function simpleRequestLogger(_cfg = {}) {
|
|
|
36
36
|
next();
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
exports.
|
|
39
|
+
exports.simpleRequestLoggerMiddleware = simpleRequestLoggerMiddleware;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Server } from 'http';
|
|
3
|
-
import { Application } from 'express';
|
|
4
3
|
import { SentrySharedService } from '../sentry/sentry.shared.service';
|
|
5
4
|
import { DefaultAppCfg } from './createDefaultApp.model';
|
|
5
|
+
import { BackendApplication } from './server.model';
|
|
6
6
|
/**
|
|
7
7
|
* If DefaultAppCfg.resources is passed and `expressApp` is not passed - it will call createDefaultApp(cfg).
|
|
8
8
|
*/
|
|
@@ -11,7 +11,7 @@ export interface StartServerCfg extends DefaultAppCfg {
|
|
|
11
11
|
* @default process.env.PORT || 8080
|
|
12
12
|
*/
|
|
13
13
|
port?: number;
|
|
14
|
-
expressApp?:
|
|
14
|
+
expressApp?: BackendApplication;
|
|
15
15
|
/**
|
|
16
16
|
* Server will wait for promise to resolve until shutting down.
|
|
17
17
|
* (with a timeout)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JsonSchema, JsonSchemaBuilder } from '@naturalcycles/js-lib';
|
|
2
2
|
import { AjvSchema, AjvValidationError } from '@naturalcycles/nodejs-lib';
|
|
3
|
-
import {
|
|
4
|
-
import { ReqValidationOptions } from './
|
|
5
|
-
export declare function validateBody(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>):
|
|
6
|
-
export declare function validateParams(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>):
|
|
7
|
-
export declare function validateQuery(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>):
|
|
3
|
+
import { BackendRequestHandler } from './server.model';
|
|
4
|
+
import { ReqValidationOptions } from './reqValidationMiddleware';
|
|
5
|
+
export declare function validateBody(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
6
|
+
export declare function validateParams(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
7
|
+
export declare function validateQuery(schema: JsonSchema | JsonSchemaBuilder | AjvSchema, opt?: ReqValidationOptions<AjvValidationError>): BackendRequestHandler;
|
|
File without changes
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { GetGotOptions, Got } from '@naturalcycles/nodejs-lib';
|
|
2
|
+
import { BackendApplication } from '../index';
|
|
3
|
+
import { BackendRequestHandlerCfg } from '../server/createDefaultApp.model';
|
|
4
4
|
export interface ExpressApp extends Got {
|
|
5
5
|
close(): Promise<void>;
|
|
6
6
|
}
|
|
7
7
|
declare class ExpressTestService {
|
|
8
|
-
createAppFromResource(resource:
|
|
9
|
-
createAppFromResources(resources:
|
|
10
|
-
createApp(app:
|
|
8
|
+
createAppFromResource(resource: BackendRequestHandlerCfg, opt?: GetGotOptions): ExpressApp;
|
|
9
|
+
createAppFromResources(resources: BackendRequestHandlerCfg[], opt?: GetGotOptions): ExpressApp;
|
|
10
|
+
createApp(app: BackendApplication, opt?: GetGotOptions): ExpressApp;
|
|
11
11
|
/**
|
|
12
12
|
* Creates a "Default Express App" with provided resources.
|
|
13
13
|
* Starts an http server on '127.0.0.1' and random available port.
|
|
@@ -9,17 +9,17 @@ const index_1 = require("../index");
|
|
|
9
9
|
// await app.close()
|
|
10
10
|
// })
|
|
11
11
|
class ExpressTestService {
|
|
12
|
-
createAppFromResource(resource) {
|
|
12
|
+
createAppFromResource(resource, opt) {
|
|
13
13
|
return this.createApp((0, index_1.createDefaultApp)({
|
|
14
14
|
resources: [resource],
|
|
15
|
-
}));
|
|
15
|
+
}), opt);
|
|
16
16
|
}
|
|
17
|
-
createAppFromResources(resources) {
|
|
17
|
+
createAppFromResources(resources, opt) {
|
|
18
18
|
return this.createApp((0, index_1.createDefaultApp)({
|
|
19
19
|
resources,
|
|
20
|
-
}));
|
|
20
|
+
}), opt);
|
|
21
21
|
}
|
|
22
|
-
createApp(app) {
|
|
22
|
+
createApp(app, opt) {
|
|
23
23
|
const server = this.createTestServer(app);
|
|
24
24
|
const { port } = server.address();
|
|
25
25
|
const prefixUrl = `http://127.0.0.1:${port}`;
|
|
@@ -27,6 +27,9 @@ class ExpressTestService {
|
|
|
27
27
|
prefixUrl,
|
|
28
28
|
responseType: 'json',
|
|
29
29
|
retry: 0,
|
|
30
|
+
logStart: true,
|
|
31
|
+
logFinished: true,
|
|
32
|
+
...opt,
|
|
30
33
|
});
|
|
31
34
|
got.close = async () => {
|
|
32
35
|
await new Promise(resolve => server.close(resolve));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install && patch-package",
|
|
6
6
|
"serve": "APP_ENV=dev nodemon",
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
"@types/ejs": "^3.0.0",
|
|
46
46
|
"@types/js-yaml": "^4.0.0",
|
|
47
47
|
"@types/node": "^16.4.1",
|
|
48
|
-
"esbuild": "^0.13.13",
|
|
49
48
|
"esbuild-register": "^3.1.2",
|
|
50
49
|
"fastify": "^3.20.1",
|
|
51
50
|
"jest": "^27.0.1",
|
package/src/admin/admin.mw.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs'
|
|
2
2
|
import { Admin401ErrorData, HttpError, _memoFn } from '@naturalcycles/js-lib'
|
|
3
3
|
import * as ejs from 'ejs'
|
|
4
|
-
import {
|
|
4
|
+
import { BackendRequestHandler } from '../server/server.model'
|
|
5
5
|
import { BaseAdminService } from './base.admin.service'
|
|
6
6
|
import { FirebaseSharedServiceCfg } from './firebase.shared.service'
|
|
7
7
|
|
|
@@ -26,7 +26,10 @@ export interface RequireAdminCfg {
|
|
|
26
26
|
autoLogin?: boolean
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export type AdminMiddleware = (
|
|
29
|
+
export type AdminMiddleware = (
|
|
30
|
+
reqPermissions?: string[],
|
|
31
|
+
cfg?: RequireAdminCfg,
|
|
32
|
+
) => BackendRequestHandler
|
|
30
33
|
|
|
31
34
|
export function createAdminMiddleware(
|
|
32
35
|
adminService: BaseAdminService,
|
|
@@ -49,7 +52,7 @@ export function requireAdminPermissions(
|
|
|
49
52
|
adminService: BaseAdminService,
|
|
50
53
|
reqPermissions: string[] = [],
|
|
51
54
|
cfg: RequireAdminCfg = {},
|
|
52
|
-
):
|
|
55
|
+
): BackendRequestHandler {
|
|
53
56
|
const { loginHtmlPath = '/login.html', urlStartsWith, apiHost, autoLogin = true } = cfg
|
|
54
57
|
|
|
55
58
|
return async (req, res, next) => {
|
|
@@ -78,7 +81,7 @@ interface LoginHtmlCfg {
|
|
|
78
81
|
firebaseAuthProvider: string
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
export function loginHtml(firebaseServiceCfg: FirebaseSharedServiceCfg):
|
|
84
|
+
export function loginHtml(firebaseServiceCfg: FirebaseSharedServiceCfg): BackendRequestHandler {
|
|
82
85
|
const {
|
|
83
86
|
apiKey: firebaseApiKey,
|
|
84
87
|
authDomain: firebaseAuthDomain,
|