@naturalcycles/backend-lib 8.0.4 → 9.0.1
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/adminMiddleware.d.ts +3 -3
- package/dist/admin/adminMiddleware.js +12 -18
- package/dist/admin/base.admin.service.d.ts +1 -1
- package/dist/admin/base.admin.service.js +9 -13
- package/dist/admin/firebase.shared.service.d.ts +3 -3
- package/dist/admin/firebase.shared.service.js +12 -15
- package/dist/admin/secureHeaderMiddleware.d.ts +2 -2
- package/dist/admin/secureHeaderMiddleware.js +7 -10
- package/dist/bin/deploy-gae.js +9 -11
- package/dist/bin/deploy-health-check.js +6 -8
- package/dist/bin/deploy-prepare.js +5 -7
- package/dist/bin/undeploy-gae.js +5 -7
- package/dist/db/httpDB.js +7 -11
- package/dist/db/httpDBRequestHandler.d.ts +1 -1
- package/dist/db/httpDBRequestHandler.js +27 -29
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -7
- package/dist/deploy/backend.cfg.util.js +6 -9
- package/dist/deploy/deploy.model.js +1 -2
- package/dist/deploy/deploy.util.d.ts +2 -2
- package/dist/deploy/deploy.util.js +25 -33
- package/dist/deploy/deployGae.d.ts +2 -2
- package/dist/deploy/deployGae.js +23 -27
- package/dist/deploy/deployHealthCheck.js +16 -20
- package/dist/deploy/deployPrepare.d.ts +1 -1
- package/dist/deploy/deployPrepare.js +17 -21
- package/dist/deploy/index.d.ts +8 -8
- package/dist/deploy/index.js +6 -14
- package/dist/env/env.shared.service.js +8 -12
- package/dist/index.d.ts +33 -33
- package/dist/index.js +34 -38
- package/dist/paths.cnst.js +8 -9
- package/dist/sentry/sentry.shared.service.js +11 -15
- package/dist/server/asyncLocalStorageMiddleware.d.ts +1 -1
- package/dist/server/asyncLocalStorageMiddleware.js +9 -15
- package/dist/server/basicAuthMiddleware.d.ts +1 -1
- package/dist/server/basicAuthMiddleware.js +5 -8
- package/dist/server/bodyParserTimeoutMiddleware.d.ts +1 -1
- package/dist/server/bodyParserTimeoutMiddleware.js +5 -9
- package/dist/server/createDefaultApp.d.ts +3 -3
- package/dist/server/createDefaultApp.js +22 -23
- package/dist/server/createDefaultApp.model.d.ts +3 -3
- package/dist/server/createDefaultApp.model.js +1 -2
- package/dist/server/deployInfo.util.d.ts +1 -1
- package/dist/server/deployInfo.util.js +5 -8
- package/dist/server/genericErrorMiddleware.d.ts +2 -2
- package/dist/server/genericErrorMiddleware.js +6 -10
- package/dist/server/getDefaultRouter.d.ts +1 -1
- package/dist/server/getDefaultRouter.js +3 -6
- package/dist/server/logMiddleware.d.ts +1 -1
- package/dist/server/logMiddleware.js +12 -16
- package/dist/server/methodOverrideMiddleware.d.ts +1 -1
- package/dist/server/methodOverrideMiddleware.js +1 -4
- package/dist/server/notFoundMiddleware.d.ts +1 -1
- package/dist/server/notFoundMiddleware.js +3 -6
- package/dist/server/okMiddleware.d.ts +1 -1
- package/dist/server/okMiddleware.js +1 -4
- package/dist/server/request.log.util.d.ts +1 -1
- package/dist/server/request.log.util.js +7 -11
- package/dist/server/request.util.d.ts +1 -1
- package/dist/server/request.util.js +1 -4
- package/dist/server/requestTimeoutMiddleware.d.ts +1 -1
- package/dist/server/requestTimeoutMiddleware.js +9 -13
- package/dist/server/safeJsonMiddleware.d.ts +1 -1
- package/dist/server/safeJsonMiddleware.js +3 -6
- package/dist/server/server.model.js +1 -2
- package/dist/server/server.util.js +1 -4
- package/dist/server/serverStatsMiddleware.d.ts +1 -1
- package/dist/server/serverStatsMiddleware.js +19 -24
- package/dist/server/serverStatusMiddleware.d.ts +1 -1
- package/dist/server/serverStatusMiddleware.js +12 -16
- package/dist/server/simpleRequestLoggerMiddleware.d.ts +1 -1
- package/dist/server/simpleRequestLoggerMiddleware.js +8 -11
- package/dist/server/startServer.d.ts +1 -1
- package/dist/server/startServer.js +18 -22
- package/dist/server/startServer.model.d.ts +3 -3
- package/dist/server/startServer.model.js +1 -2
- package/dist/server/validation/validateMiddleware.d.ts +2 -2
- package/dist/server/validation/validateMiddleware.js +9 -15
- package/dist/server/validation/validateRequest.d.ts +1 -1
- package/dist/server/validation/validateRequest.js +6 -9
- package/dist/server/validation/zodValidateMiddleware.d.ts +2 -2
- package/dist/server/validation/zodValidateMiddleware.js +6 -9
- package/dist/testing/express.test.service.d.ts +5 -5
- package/dist/testing/express.test.service.js +16 -14
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -5
- package/dist/util.js +2 -6
- package/package.json +7 -7
- package/src/admin/adminMiddleware.ts +5 -4
- package/src/admin/base.admin.service.ts +1 -1
- package/src/admin/firebase.shared.service.ts +7 -6
- package/src/admin/secureHeaderMiddleware.ts +4 -4
- package/src/bin/deploy-gae.ts +3 -3
- package/src/bin/deploy-health-check.ts +1 -1
- package/src/bin/deploy-prepare.ts +1 -1
- package/src/bin/undeploy-gae.ts +1 -1
- package/src/db/httpDBRequestHandler.ts +4 -3
- package/src/db/index.ts +3 -3
- package/src/deploy/backend.cfg.util.ts +1 -1
- package/src/deploy/deploy.util.ts +3 -4
- package/src/deploy/deployGae.ts +6 -6
- package/src/deploy/deployHealthCheck.ts +1 -1
- package/src/deploy/deployPrepare.ts +6 -5
- package/src/deploy/index.ts +8 -8
- package/src/index.ts +33 -33
- package/src/paths.cnst.ts +6 -2
- package/src/sentry/sentry.shared.service.ts +1 -1
- package/src/server/asyncLocalStorageMiddleware.ts +2 -2
- package/src/server/basicAuthMiddleware.ts +1 -1
- package/src/server/bodyParserTimeoutMiddleware.ts +2 -2
- package/src/server/createDefaultApp.model.ts +3 -3
- package/src/server/createDefaultApp.ts +16 -14
- package/src/server/deployInfo.util.ts +1 -1
- package/src/server/genericErrorMiddleware.ts +2 -2
- package/src/server/getDefaultRouter.ts +1 -1
- package/src/server/logMiddleware.ts +1 -1
- package/src/server/methodOverrideMiddleware.ts +1 -1
- package/src/server/notFoundMiddleware.ts +2 -2
- package/src/server/okMiddleware.ts +1 -1
- package/src/server/request.log.util.ts +1 -1
- package/src/server/request.util.ts +1 -1
- package/src/server/requestTimeoutMiddleware.ts +2 -2
- package/src/server/safeJsonMiddleware.ts +1 -1
- package/src/server/serverStatsMiddleware.ts +3 -3
- package/src/server/serverStatusMiddleware.ts +2 -2
- package/src/server/simpleRequestLoggerMiddleware.ts +3 -3
- package/src/server/startServer.model.ts +3 -3
- package/src/server/startServer.ts +4 -7
- package/src/server/validation/validateMiddleware.ts +2 -2
- package/src/server/validation/validateRequest.ts +1 -1
- package/src/server/validation/zodValidateMiddleware.ts +2 -2
- package/src/testing/express.test.service.ts +20 -11
- package/src/testing/index.ts +2 -2
package/dist/paths.cnst.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.testDir = `${exports.srcDir}/test`;
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = dirname(__filename);
|
|
5
|
+
export const projectDir = join(__dirname, '/..');
|
|
6
|
+
export const resourcesDir = `${projectDir}/resources`;
|
|
7
|
+
export const srcDir = `${projectDir}/src`;
|
|
8
|
+
export const testDir = `${srcDir}/test`;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
const index_1 = require("../index");
|
|
1
|
+
import { _anyToError, _isErrorObject } from '@naturalcycles/js-lib';
|
|
2
|
+
import { _inspect } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import { getRequestLogger } from '../index.js';
|
|
7
4
|
const sentrySeverityMap = {
|
|
8
5
|
debug: 'log',
|
|
9
6
|
info: 'log',
|
|
@@ -24,7 +21,7 @@ const INSPECT_OPT = {
|
|
|
24
21
|
* }
|
|
25
22
|
*
|
|
26
23
|
*/
|
|
27
|
-
class SentrySharedService {
|
|
24
|
+
export class SentrySharedService {
|
|
28
25
|
constructor(sentryServiceCfg) {
|
|
29
26
|
this.sentry = sentryServiceCfg.sentry;
|
|
30
27
|
}
|
|
@@ -59,12 +56,12 @@ class SentrySharedService {
|
|
|
59
56
|
*/
|
|
60
57
|
captureException(err_, logError = true) {
|
|
61
58
|
// normalize the error
|
|
62
|
-
const err =
|
|
63
|
-
const data =
|
|
59
|
+
const err = _anyToError(err_);
|
|
60
|
+
const data = _isErrorObject(err) ? err.data : undefined;
|
|
64
61
|
// Using request-aware logger here
|
|
65
62
|
if (logError) {
|
|
66
63
|
// Log both the error and attached ErrorData (if any)
|
|
67
|
-
|
|
64
|
+
getRequestLogger().error('captureException:', ...[err_, data].filter(Boolean));
|
|
68
65
|
}
|
|
69
66
|
if (data?.report === false) {
|
|
70
67
|
// Skip reporting the error
|
|
@@ -78,7 +75,7 @@ class SentrySharedService {
|
|
|
78
75
|
// It will log additional "breadcrumb object" before the error
|
|
79
76
|
// It's a Breadcrumb, not a console.log, because console.log are NOT automatically attached as Breadcrumbs in cron-job environments (outside of Express)
|
|
80
77
|
this.sentry.addBreadcrumb({
|
|
81
|
-
message:
|
|
78
|
+
message: _inspect(err, INSPECT_OPT),
|
|
82
79
|
});
|
|
83
80
|
return this.sentry.captureException(err);
|
|
84
81
|
}
|
|
@@ -86,7 +83,7 @@ class SentrySharedService {
|
|
|
86
83
|
* Returns "eventId"
|
|
87
84
|
*/
|
|
88
85
|
captureMessage(msg, level) {
|
|
89
|
-
|
|
86
|
+
getRequestLogger()[sentrySeverityMap[level] || 'log']('captureMessage:', msg);
|
|
90
87
|
return this.sentry.captureMessage(msg, level);
|
|
91
88
|
}
|
|
92
89
|
addBreadcrumb(breadcrumb) {
|
|
@@ -104,13 +101,12 @@ class SentrySharedService {
|
|
|
104
101
|
log: () => { }, // noop
|
|
105
102
|
warn: () => { }, // noop
|
|
106
103
|
error: (...args) => {
|
|
107
|
-
const message = args.map(arg =>
|
|
104
|
+
const message = args.map(arg => _inspect(arg, INSPECT_OPT)).join(' ');
|
|
108
105
|
this.sentry.addBreadcrumb({
|
|
109
106
|
message,
|
|
110
107
|
});
|
|
111
|
-
this.sentry.captureException(
|
|
108
|
+
this.sentry.captureException(_anyToError(args.length === 1 ? args[0] : args));
|
|
112
109
|
},
|
|
113
110
|
};
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
|
-
exports.SentrySharedService = SentrySharedService;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommonLogger } from '@naturalcycles/js-lib';
|
|
2
|
-
import type { BackendRequest, BackendRequestHandler } from './server.model';
|
|
2
|
+
import type { BackendRequest, BackendRequestHandler } from './server.model.js';
|
|
3
3
|
export interface RequestLocalStorage {
|
|
4
4
|
req: BackendRequest;
|
|
5
5
|
}
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.asyncLocalStorageMiddleware = asyncLocalStorageMiddleware;
|
|
5
|
-
exports.getRequest = getRequest;
|
|
6
|
-
exports.getRequestLogger = getRequestLogger;
|
|
7
|
-
const node_async_hooks_1 = require("node:async_hooks");
|
|
8
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
9
|
-
const logMiddleware_1 = require("./logMiddleware");
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { _lazyValue } from '@naturalcycles/js-lib';
|
|
3
|
+
import { ciLogger, devLogger, gaeLogger } from './logMiddleware.js';
|
|
10
4
|
const { GAE_INSTANCE, CI } = process.env;
|
|
11
5
|
const isGAE = !!GAE_INSTANCE;
|
|
12
6
|
const isCI = !!CI;
|
|
13
7
|
const isCloudRun = !!CI;
|
|
14
8
|
// Singleton, for simplicity
|
|
15
9
|
// Create it lazily (on demand)
|
|
16
|
-
const storage =
|
|
17
|
-
function asyncLocalStorageMiddleware() {
|
|
10
|
+
const storage = _lazyValue(() => new AsyncLocalStorage());
|
|
11
|
+
export function asyncLocalStorageMiddleware() {
|
|
18
12
|
return (req, _res, next) => {
|
|
19
13
|
const store = {
|
|
20
14
|
req,
|
|
@@ -22,7 +16,7 @@ function asyncLocalStorageMiddleware() {
|
|
|
22
16
|
storage().run(store, () => next());
|
|
23
17
|
};
|
|
24
18
|
}
|
|
25
|
-
function getRequest() {
|
|
19
|
+
export function getRequest() {
|
|
26
20
|
return storage().getStore()?.req;
|
|
27
21
|
}
|
|
28
22
|
/**
|
|
@@ -30,8 +24,8 @@ function getRequest() {
|
|
|
30
24
|
*
|
|
31
25
|
* @experimental
|
|
32
26
|
*/
|
|
33
|
-
function getRequestLogger() {
|
|
34
|
-
return (storage().getStore()?.req || (isGAE ?
|
|
27
|
+
export function getRequestLogger() {
|
|
28
|
+
return (storage().getStore()?.req || (isGAE ? gaeLogger : isCI || isCloudRun ? ciLogger : devLogger));
|
|
35
29
|
}
|
|
36
30
|
/**
|
|
37
31
|
* CommonLogger implementation that is Request-bound.
|
|
@@ -42,7 +36,7 @@ function getRequestLogger() {
|
|
|
42
36
|
*
|
|
43
37
|
* @experimental
|
|
44
38
|
*/
|
|
45
|
-
|
|
39
|
+
export const requestLogger = {
|
|
46
40
|
log: (...args) => getRequestLogger().log(...args),
|
|
47
41
|
warn: (...args) => getRequestLogger().warn(...args),
|
|
48
42
|
error: (...args) => getRequestLogger().error(...args),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StringMap } from '@naturalcycles/js-lib';
|
|
2
|
-
import type { BackendRequestHandler } from './server.model';
|
|
2
|
+
import type { BackendRequestHandler } from './server.model.js';
|
|
3
3
|
export interface BasicAuthMiddlewareCfg {
|
|
4
4
|
/**
|
|
5
5
|
* Map from login (Sting) to password (String).
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
function basicAuthMiddleware(cfg) {
|
|
1
|
+
import { _split } from '@naturalcycles/js-lib';
|
|
2
|
+
import { base64ToString, timingSafeStringEqual } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
export function basicAuthMiddleware(cfg) {
|
|
7
4
|
const { realm } = cfg;
|
|
8
5
|
return function basicAuthMiddlewareHandler(req, res, next) {
|
|
9
6
|
const hash = (req.headers.authorization || '').split(' ')[1];
|
|
10
7
|
if (hash) {
|
|
11
|
-
const [login, password] =
|
|
12
|
-
if (login && password &&
|
|
8
|
+
const [login, password] = _split(base64ToString(hash), ':', 2);
|
|
9
|
+
if (login && password && timingSafeStringEqual(cfg.loginPasswordMap[login], password)) {
|
|
13
10
|
return next();
|
|
14
11
|
}
|
|
15
12
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.bodyParserTimeoutMiddleware = bodyParserTimeoutMiddleware;
|
|
4
|
-
exports.clearBodyParserTimeout = clearBodyParserTimeout;
|
|
5
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
const index_1 = require("../index");
|
|
1
|
+
import { AppError } from '@naturalcycles/js-lib';
|
|
2
|
+
import { respondWithError } from '../index.js';
|
|
7
3
|
const code = 'BODY_PARSER_TIMEOUT';
|
|
8
4
|
/**
|
|
9
5
|
* Should be called BEFORE bodyParser
|
|
10
6
|
*/
|
|
11
|
-
function bodyParserTimeoutMiddleware(cfg = {}) {
|
|
7
|
+
export function bodyParserTimeoutMiddleware(cfg = {}) {
|
|
12
8
|
const { timeoutSeconds, backendResponseStatusCode, httpStatus } = {
|
|
13
9
|
timeoutSeconds: 10,
|
|
14
10
|
backendResponseStatusCode: 400,
|
|
@@ -22,7 +18,7 @@ function bodyParserTimeoutMiddleware(cfg = {}) {
|
|
|
22
18
|
if (req.bodyParserTimeout)
|
|
23
19
|
clearTimeout(req.bodyParserTimeout);
|
|
24
20
|
req.bodyParserTimeout = setTimeout(() => {
|
|
25
|
-
|
|
21
|
+
respondWithError(req, res, new AppError(httpStatus, {
|
|
26
22
|
code,
|
|
27
23
|
backendResponseStatusCode,
|
|
28
24
|
// userFriendly: true, // no, cause this error is not expected
|
|
@@ -34,7 +30,7 @@ function bodyParserTimeoutMiddleware(cfg = {}) {
|
|
|
34
30
|
/**
|
|
35
31
|
* Should be called AFTER bodyParser
|
|
36
32
|
*/
|
|
37
|
-
function clearBodyParserTimeout() {
|
|
33
|
+
export function clearBodyParserTimeout() {
|
|
38
34
|
return (req, _res, next) => {
|
|
39
35
|
clearTimeout(req.bodyParserTimeout);
|
|
40
36
|
next();
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
export declare function createDefaultApp(cfg: DefaultAppCfg): BackendApplication
|
|
1
|
+
import type { DefaultAppCfg } from './createDefaultApp.model.js';
|
|
2
|
+
import type { BackendApplication } from './server.model.js';
|
|
3
|
+
export declare function createDefaultApp(cfg: DefaultAppCfg): Promise<BackendApplication>;
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const requestTimeoutMiddleware_1 = require("./requestTimeoutMiddleware");
|
|
13
|
-
const simpleRequestLoggerMiddleware_1 = require("./simpleRequestLoggerMiddleware");
|
|
1
|
+
import cookieParser from 'cookie-parser';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
import { isGAE } from '../util.js';
|
|
5
|
+
import { asyncLocalStorageMiddleware } from './asyncLocalStorageMiddleware.js';
|
|
6
|
+
import { genericErrorMiddleware } from './genericErrorMiddleware.js';
|
|
7
|
+
import { logMiddleware } from './logMiddleware.js';
|
|
8
|
+
import { methodOverrideMiddleware } from './methodOverrideMiddleware.js';
|
|
9
|
+
import { notFoundMiddleware } from './notFoundMiddleware.js';
|
|
10
|
+
import { requestTimeoutMiddleware } from './requestTimeoutMiddleware.js';
|
|
11
|
+
import { simpleRequestLoggerMiddleware } from './simpleRequestLoggerMiddleware.js';
|
|
14
12
|
const isTest = process.env['APP_ENV'] === 'test';
|
|
15
|
-
function createDefaultApp(cfg) {
|
|
13
|
+
export async function createDefaultApp(cfg) {
|
|
16
14
|
const { sentryService } = cfg;
|
|
17
15
|
const app = express();
|
|
18
16
|
app.disable('etag');
|
|
@@ -20,16 +18,16 @@ function createDefaultApp(cfg) {
|
|
|
20
18
|
app.set('trust proxy', true);
|
|
21
19
|
// preHandlers
|
|
22
20
|
useHandlers(app, cfg.preHandlers);
|
|
23
|
-
app.use(
|
|
21
|
+
app.use(logMiddleware());
|
|
24
22
|
if (!isTest) {
|
|
25
|
-
app.use(
|
|
23
|
+
app.use(asyncLocalStorageMiddleware());
|
|
26
24
|
}
|
|
27
|
-
app.use(
|
|
28
|
-
app.use(
|
|
25
|
+
app.use(methodOverrideMiddleware());
|
|
26
|
+
app.use(requestTimeoutMiddleware());
|
|
29
27
|
// app.use(serverStatsMiddleware()) // disabled by default
|
|
30
28
|
// app.use(bodyParserTimeout()) // removed by default
|
|
31
|
-
if (!
|
|
32
|
-
app.use(
|
|
29
|
+
if (!isGAE() && !isTest) {
|
|
30
|
+
app.use(simpleRequestLoggerMiddleware());
|
|
33
31
|
}
|
|
34
32
|
// app.use(safeJsonMiddleware()) // optional
|
|
35
33
|
// accepts application/json
|
|
@@ -51,7 +49,8 @@ function createDefaultApp(cfg) {
|
|
|
51
49
|
app.use(cookieParser());
|
|
52
50
|
if (!isTest) {
|
|
53
51
|
// leaks, load lazily
|
|
54
|
-
|
|
52
|
+
const { default: helmet } = await import('helmet');
|
|
53
|
+
app.use(helmet({
|
|
55
54
|
contentSecurityPolicy: false, // to allow "admin 401 auto-redirect"
|
|
56
55
|
}));
|
|
57
56
|
}
|
|
@@ -74,7 +73,7 @@ function createDefaultApp(cfg) {
|
|
|
74
73
|
// postHandlers
|
|
75
74
|
useHandlers(app, cfg.postHandlers);
|
|
76
75
|
// Generic 404 handler
|
|
77
|
-
app.use(
|
|
76
|
+
app.use(notFoundMiddleware());
|
|
78
77
|
// currently disabled as not necessary (because genericErrorMiddleware already reports to sentry)
|
|
79
78
|
// if (sentryService) {
|
|
80
79
|
// sentryService.sentry.setupExpressErrorHandler(app)
|
|
@@ -82,7 +81,7 @@ function createDefaultApp(cfg) {
|
|
|
82
81
|
// Generic error handler
|
|
83
82
|
// It handles errors, returns proper status, does sentry.captureException(),
|
|
84
83
|
// assigns err.data.errorId from sentry
|
|
85
|
-
app.use(
|
|
84
|
+
app.use(genericErrorMiddleware({ sentryService, ...cfg.genericErrorMwCfg }));
|
|
86
85
|
return app;
|
|
87
86
|
}
|
|
88
87
|
function useHandlers(app, handlers = []) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Options, OptionsJson, OptionsUrlencoded } from 'body-parser';
|
|
2
2
|
import type { CorsOptions } from 'cors';
|
|
3
|
-
import type { SentrySharedService } from '../sentry/sentry.shared.service';
|
|
4
|
-
import type { GenericErrorMiddlewareCfg } from './genericErrorMiddleware';
|
|
5
|
-
import type { BackendRequestHandler } from './server.model';
|
|
3
|
+
import type { SentrySharedService } from '../sentry/sentry.shared.service.js';
|
|
4
|
+
import type { GenericErrorMiddlewareCfg } from './genericErrorMiddleware.js';
|
|
5
|
+
import type { BackendRequestHandler } from './server.model.js';
|
|
6
6
|
/**
|
|
7
7
|
* Plain RequestHandler can be provided - then it's mounted to /
|
|
8
8
|
* Otherwise `path` can be provided to specify mounting point.
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { DeployInfo } from '../deploy';
|
|
1
|
+
import type { DeployInfo } from '../deploy/index.js';
|
|
2
2
|
export declare const getDeployInfo: ((projectDir: string) => DeployInfo) & import("@naturalcycles/js-lib").MemoizedFunction;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
exports.getDeployInfo = (0, js_lib_1._memoFn)((projectDir) => {
|
|
1
|
+
import { _memoFn, localTime } from '@naturalcycles/js-lib';
|
|
2
|
+
import { fs2 } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
export const getDeployInfo = _memoFn((projectDir) => {
|
|
7
4
|
const deployInfoPath = `${projectDir}/deployInfo.json`;
|
|
8
5
|
try {
|
|
9
|
-
return
|
|
6
|
+
return fs2.readJson(deployInfoPath);
|
|
10
7
|
}
|
|
11
8
|
catch {
|
|
12
9
|
// console.error(`cannot read ${deployInfoPath}, returning empty version`)
|
|
@@ -22,6 +19,6 @@ function getDeployInfoStub(stub = '') {
|
|
|
22
19
|
versionUrl: stub,
|
|
23
20
|
gitBranch: stub,
|
|
24
21
|
gitRev: stub,
|
|
25
|
-
ts:
|
|
22
|
+
ts: localTime.nowUnix(),
|
|
26
23
|
};
|
|
27
24
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ErrorObject } from '@naturalcycles/js-lib';
|
|
2
|
-
import type { SentrySharedService } from '../sentry/sentry.shared.service';
|
|
3
|
-
import type { BackendErrorRequestHandler, BackendRequest, BackendResponse } from './server.model';
|
|
2
|
+
import type { SentrySharedService } from '../sentry/sentry.shared.service.js';
|
|
3
|
+
import type { BackendErrorRequestHandler, BackendRequest, BackendResponse } from './server.model.js';
|
|
4
4
|
export interface GenericErrorMiddlewareCfg {
|
|
5
5
|
sentryService?: SentrySharedService;
|
|
6
6
|
/**
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.genericErrorMiddleware = genericErrorMiddleware;
|
|
4
|
-
exports.respondWithError = respondWithError;
|
|
5
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
1
|
+
import { _anyToError, _errorLikeToErrorObject, _filterUndefinedValues } from '@naturalcycles/js-lib';
|
|
6
2
|
const { APP_ENV } = process.env;
|
|
7
3
|
const includeErrorStack = APP_ENV === 'dev';
|
|
8
4
|
// Hacky way to store the sentryService, so it's available to `respondWithError` function
|
|
@@ -14,7 +10,7 @@ let formatError;
|
|
|
14
10
|
* Returns HTTP code based on err.data.backendResponseStatusCode (default to 500).
|
|
15
11
|
* Sends json payload as ErrorResponse, transformed via errorSharedUtil.
|
|
16
12
|
*/
|
|
17
|
-
function genericErrorMiddleware(cfg = {}) {
|
|
13
|
+
export function genericErrorMiddleware(cfg = {}) {
|
|
18
14
|
sentryService ||= cfg.sentryService;
|
|
19
15
|
reportOnly5xx = cfg.reportOnly5xx || false;
|
|
20
16
|
formatError = cfg.formatError;
|
|
@@ -33,7 +29,7 @@ function genericErrorMiddleware(cfg = {}) {
|
|
|
33
29
|
respondWithError(req, res, err);
|
|
34
30
|
};
|
|
35
31
|
}
|
|
36
|
-
function respondWithError(req, res, err) {
|
|
32
|
+
export function respondWithError(req, res, err) {
|
|
37
33
|
const { headersSent } = res;
|
|
38
34
|
if (headersSent) {
|
|
39
35
|
req.error(`error after headersSent:`, err);
|
|
@@ -41,20 +37,20 @@ function respondWithError(req, res, err) {
|
|
|
41
37
|
else {
|
|
42
38
|
req.error(err);
|
|
43
39
|
}
|
|
44
|
-
const originalError =
|
|
40
|
+
const originalError = _anyToError(err);
|
|
45
41
|
let errorId;
|
|
46
42
|
if (sentryService && shouldReportToSentry(originalError)) {
|
|
47
43
|
errorId = sentryService.captureException(originalError, false);
|
|
48
44
|
}
|
|
49
45
|
if (headersSent)
|
|
50
46
|
return;
|
|
51
|
-
const httpError =
|
|
47
|
+
const httpError = _errorLikeToErrorObject(originalError);
|
|
52
48
|
if (!includeErrorStack)
|
|
53
49
|
delete httpError.stack;
|
|
54
50
|
httpError.data.errorId = errorId;
|
|
55
51
|
httpError.data.backendResponseStatusCode ||= 500; // default to 500
|
|
56
52
|
httpError.data.headersSent = headersSent || undefined;
|
|
57
|
-
|
|
53
|
+
_filterUndefinedValues(httpError.data, true);
|
|
58
54
|
formatError?.(httpError); // Mutates
|
|
59
55
|
res.status(httpError.data.backendResponseStatusCode).json({
|
|
60
56
|
error: httpError,
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDefaultRouter = getDefaultRouter;
|
|
4
|
-
const express_1 = require("express");
|
|
1
|
+
import { Router } from 'express';
|
|
5
2
|
/**
|
|
6
3
|
* Convenience method.
|
|
7
4
|
*/
|
|
8
|
-
function getDefaultRouter(defaultHandlers = []) {
|
|
9
|
-
const router =
|
|
5
|
+
export function getDefaultRouter(defaultHandlers = []) {
|
|
6
|
+
const router = Router();
|
|
10
7
|
// Use default handlers
|
|
11
8
|
defaultHandlers.forEach(h => router.use(h));
|
|
12
9
|
return router;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommonLogger } from '@naturalcycles/js-lib';
|
|
2
|
-
import type { BackendRequestHandler } from './server.model';
|
|
2
|
+
import type { BackendRequestHandler } from './server.model.js';
|
|
3
3
|
/**
|
|
4
4
|
* Logger that logs in AppEngine format.
|
|
5
5
|
* To be used in outside-of-request situations (otherwise req.log should be used).
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.ciLogger = exports.devLogger = exports.gaeLogger = void 0;
|
|
4
|
-
exports.logMiddleware = logMiddleware;
|
|
5
|
-
const node_util_1 = require("node:util");
|
|
6
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
1
|
+
import { inspect } from 'node:util';
|
|
2
|
+
import { _inspect, dimGrey } from '@naturalcycles/nodejs-lib';
|
|
7
3
|
const { GOOGLE_CLOUD_PROJECT, GAE_INSTANCE, APP_ENV } = process.env;
|
|
8
4
|
const isGAE = !!GAE_INSTANCE;
|
|
9
5
|
// const isCloudRun = !!K_SERVICE
|
|
@@ -15,7 +11,7 @@ let reqCounter = 0;
|
|
|
15
11
|
* Logger that logs in AppEngine format.
|
|
16
12
|
* To be used in outside-of-request situations (otherwise req.log should be used).
|
|
17
13
|
*/
|
|
18
|
-
|
|
14
|
+
export const gaeLogger = {
|
|
19
15
|
log: (...args) => logToAppEngine({}, args),
|
|
20
16
|
warn: (...args) => logToAppEngine({ severity: 'WARNING' }, args),
|
|
21
17
|
error: (...args) => logToAppEngine({ severity: 'ERROR' }, args),
|
|
@@ -24,7 +20,7 @@ exports.gaeLogger = {
|
|
|
24
20
|
* Fancy development logger, to be used in outside-of-request situations
|
|
25
21
|
* (otherwise req.log should be used).
|
|
26
22
|
*/
|
|
27
|
-
|
|
23
|
+
export const devLogger = {
|
|
28
24
|
log: (...args) => logToDev(null, args),
|
|
29
25
|
warn: (...args) => logToDev(null, args),
|
|
30
26
|
error: (...args) => logToDev(null, args),
|
|
@@ -32,7 +28,7 @@ exports.devLogger = {
|
|
|
32
28
|
/**
|
|
33
29
|
* Same as devLogger, but without colors (e.g to not confuse Sentry).
|
|
34
30
|
*/
|
|
35
|
-
|
|
31
|
+
export const ciLogger = {
|
|
36
32
|
log: (...args) => logToCI(args),
|
|
37
33
|
warn: (...args) => logToCI(args),
|
|
38
34
|
error: (...args) => logToCI(args),
|
|
@@ -40,15 +36,15 @@ exports.ciLogger = {
|
|
|
40
36
|
// Documented here: https://cloud.google.com/logging/docs/structured-logging
|
|
41
37
|
function logToAppEngine(meta, args) {
|
|
42
38
|
console.log(JSON.stringify({
|
|
43
|
-
message: args.map(a => (typeof a === 'string' ? a :
|
|
39
|
+
message: args.map(a => (typeof a === 'string' ? a : inspect(a))).join(' '),
|
|
44
40
|
...meta,
|
|
45
41
|
}));
|
|
46
42
|
}
|
|
47
43
|
function logToDev(requestId, args) {
|
|
48
44
|
// Run on local machine
|
|
49
45
|
console.log([
|
|
50
|
-
requestId ? [
|
|
51
|
-
...args.map(a =>
|
|
46
|
+
requestId ? [dimGrey(`[${requestId}]`)] : [],
|
|
47
|
+
...args.map(a => _inspect(a, { includeErrorStack: true, colors: true })),
|
|
52
48
|
].join(' '));
|
|
53
49
|
}
|
|
54
50
|
/**
|
|
@@ -56,9 +52,9 @@ function logToDev(requestId, args) {
|
|
|
56
52
|
* This is to not confuse e.g Sentry when it picks up messages with colors
|
|
57
53
|
*/
|
|
58
54
|
function logToCI(args) {
|
|
59
|
-
console.log(args.map(a =>
|
|
55
|
+
console.log(args.map(a => _inspect(a, { includeErrorStack: true, colors: false })).join(' '));
|
|
60
56
|
}
|
|
61
|
-
function logMiddleware() {
|
|
57
|
+
export function logMiddleware() {
|
|
62
58
|
if (isGAE) {
|
|
63
59
|
if (GOOGLE_CLOUD_PROJECT) {
|
|
64
60
|
return function appEngineLogHandler(req, _res, next) {
|
|
@@ -77,13 +73,13 @@ function logMiddleware() {
|
|
|
77
73
|
req.requestId = trace;
|
|
78
74
|
}
|
|
79
75
|
else {
|
|
80
|
-
Object.assign(req,
|
|
76
|
+
Object.assign(req, gaeLogger);
|
|
81
77
|
}
|
|
82
78
|
next();
|
|
83
79
|
};
|
|
84
80
|
}
|
|
85
81
|
return function appEngineLogHandler(req, _res, next) {
|
|
86
|
-
Object.assign(req,
|
|
82
|
+
Object.assign(req, gaeLogger);
|
|
87
83
|
next();
|
|
88
84
|
};
|
|
89
85
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.methodOverrideMiddleware = methodOverrideMiddleware;
|
|
4
|
-
function methodOverrideMiddleware(cfg = {}) {
|
|
1
|
+
export function methodOverrideMiddleware(cfg = {}) {
|
|
5
2
|
const { methodKey } = {
|
|
6
3
|
methodKey: '_method',
|
|
7
4
|
...cfg,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { BackendRequestHandler } from './server.model';
|
|
1
|
+
import type { BackendRequestHandler } from './server.model.js';
|
|
2
2
|
export declare function notFoundMiddleware(): BackendRequestHandler;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.notFoundMiddleware = notFoundMiddleware;
|
|
4
|
-
const request_util_1 = require("./request.util");
|
|
5
|
-
function notFoundMiddleware() {
|
|
1
|
+
import { getRequestEndpoint } from './request.util.js';
|
|
2
|
+
export function notFoundMiddleware() {
|
|
6
3
|
return (req, res) => {
|
|
7
|
-
res.status(404).send(`404 Not Found: ${
|
|
4
|
+
res.status(404).send(`404 Not Found: ${getRequestEndpoint(req)}`);
|
|
8
5
|
};
|
|
9
6
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { BackendRequestHandler } from './server.model';
|
|
1
|
+
import type { BackendRequestHandler } from './server.model.js';
|
|
2
2
|
export declare function okMiddleware(): BackendRequestHandler;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { BackendRequest } from './server.model';
|
|
1
|
+
import type { BackendRequest } from './server.model.js';
|
|
2
2
|
export declare function logRequest(req: BackendRequest, statusCode: number, ...tokens: any[]): void;
|
|
3
3
|
export declare function coloredHttpCode(statusCode: number): string;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.coloredHttpCode = coloredHttpCode;
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
function logRequest(req, statusCode, ...tokens) {
|
|
7
|
-
req[logLevel(statusCode)]([coloredHttpCode(statusCode), req.method, (0, nodejs_lib_1.boldGrey)(req.url), ...tokens].join(' '));
|
|
1
|
+
import { boldGrey, green, red, yellow } from '@naturalcycles/nodejs-lib';
|
|
2
|
+
export function logRequest(req, statusCode, ...tokens) {
|
|
3
|
+
req[logLevel(statusCode)]([coloredHttpCode(statusCode), req.method, boldGrey(req.url), ...tokens].join(' '));
|
|
8
4
|
}
|
|
9
|
-
function coloredHttpCode(statusCode) {
|
|
5
|
+
export function coloredHttpCode(statusCode) {
|
|
10
6
|
if (statusCode >= 200 && statusCode < 400)
|
|
11
|
-
return
|
|
7
|
+
return green(statusCode);
|
|
12
8
|
if (statusCode >= 400 && statusCode < 500)
|
|
13
|
-
return
|
|
14
|
-
return
|
|
9
|
+
return yellow(statusCode);
|
|
10
|
+
return red(statusCode);
|
|
15
11
|
}
|
|
16
12
|
function logLevel(statusCode) {
|
|
17
13
|
if (!statusCode || statusCode < 400)
|