@naturalcycles/backend-lib 4.4.1 → 4.5.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/cfg/tsconfig.json +1 -1
- package/dist/db/httpDB.d.ts +1 -1
- package/dist/deploy/deploy.util.js +1 -1
- package/dist/sentry/sentry.shared.service.d.ts +2 -3
- package/dist/sentry/sentry.shared.service.js +6 -8
- package/dist/server/reqValidationMiddleware.js +1 -3
- package/dist/server/serverStatusMiddleware.js +5 -5
- package/dist/server/validateMiddleware.js +1 -3
- package/package.json +6 -7
- package/src/db/httpDB.ts +2 -2
- package/src/deploy/deploy.util.ts +1 -1
- package/src/sentry/sentry.shared.service.ts +9 -11
- package/src/server/bodyParserTimeoutMiddleware.ts +1 -1
- package/src/server/reqValidationMiddleware.ts +1 -3
- package/src/server/requestTimeoutMiddleware.ts +2 -2
- package/src/server/server.util.ts +4 -2
- package/src/server/serverStatsMiddleware.ts +1 -1
- package/src/server/serverStatusMiddleware.ts +5 -5
- package/src/server/validateMiddleware.ts +1 -3
package/cfg/tsconfig.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"noFallthroughCasesInSwitch": true,
|
|
21
21
|
"forceConsistentCasingInFileNames": true,
|
|
22
22
|
"resolveJsonModule": true,
|
|
23
|
-
"suppressImplicitAnyIndexErrors":
|
|
23
|
+
"suppressImplicitAnyIndexErrors": false,
|
|
24
24
|
"noImplicitOverride": true,
|
|
25
25
|
"noUncheckedIndexedAccess": true,
|
|
26
26
|
"noPropertyAccessFromIndexSignature": true,
|
package/dist/db/httpDB.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
19
19
|
getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: CommonDBOptions): Promise<ROW[]>;
|
|
20
20
|
runQuery<ROW extends ObjectWithId>(query: DBQuery<ROW>, opt?: CommonDBOptions): Promise<RunQueryResult<ROW>>;
|
|
21
21
|
runQueryCount<ROW extends ObjectWithId>(query: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
|
|
22
|
-
saveBatch<ROW extends ObjectWithId
|
|
22
|
+
saveBatch<ROW extends Partial<ObjectWithId>>(table: string, rows: ROW[], opt?: CommonDBSaveOptions<ROW>): Promise<void>;
|
|
23
23
|
deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number>;
|
|
24
24
|
deleteByQuery<ROW extends ObjectWithId>(query: DBQuery<ROW>, opt?: CommonDBOptions): Promise<number>;
|
|
25
25
|
streamQuery<ROW extends ObjectWithId>(_q: DBQuery<ROW>, _opt?: CommonDBStreamOptions): ReadableTyped<ROW>;
|
|
@@ -34,7 +34,7 @@ exports.createAndSaveDeployInfo = createAndSaveDeployInfo;
|
|
|
34
34
|
async function createDeployInfo(backendCfg) {
|
|
35
35
|
const simpleGit = require('simple-git/promise'); // lazy load
|
|
36
36
|
const git = simpleGit('.');
|
|
37
|
-
const now = (0, js_lib_1.localTime)()
|
|
37
|
+
const now = (0, js_lib_1.localTime)();
|
|
38
38
|
const gitBranch = (await git.status()).current;
|
|
39
39
|
const gitRev = (await git.revparse(['HEAD'])).slice(0, 7);
|
|
40
40
|
let { gaeProject, gaeProjectByBranch = {}, gaeService, gaeServiceByBranch = {}, serviceWithBranchName, prodBranch, branchesWithTimestampVersions = [], } = backendCfg;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CommonLogger } from '@naturalcycles/js-lib';
|
|
2
|
-
import {
|
|
3
|
-
import type { Breadcrumb, NodeOptions } from '@sentry/node';
|
|
2
|
+
import type { Breadcrumb, NodeOptions, SeverityLevel } from '@sentry/node';
|
|
4
3
|
import type * as SentryLib from '@sentry/node';
|
|
5
4
|
import { BackendErrorRequestHandler, BackendRequestHandler } from '../index';
|
|
6
5
|
export interface SentrySharedServiceCfg extends NodeOptions {
|
|
@@ -34,7 +33,7 @@ export declare class SentrySharedService {
|
|
|
34
33
|
/**
|
|
35
34
|
* Returns "eventId"
|
|
36
35
|
*/
|
|
37
|
-
captureMessage(msg: string, level?:
|
|
36
|
+
captureMessage(msg: string, level?: SeverityLevel): string;
|
|
38
37
|
addBreadcrumb(breadcrumb: Breadcrumb): void;
|
|
39
38
|
/**
|
|
40
39
|
* Currently it will only use `logger.error` ("error" level) and ignore `log` and `warn`.
|
|
@@ -4,16 +4,14 @@ exports.SentrySharedService = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
6
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
7
|
-
const node_1 = require("@sentry/node");
|
|
8
7
|
const index_1 = require("../index");
|
|
9
8
|
const sentrySeverityMap = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[node_1.Severity.Fatal]: 'error',
|
|
9
|
+
debug: 'log',
|
|
10
|
+
info: 'log',
|
|
11
|
+
log: 'log',
|
|
12
|
+
warning: 'warn',
|
|
13
|
+
error: 'error',
|
|
14
|
+
fatal: 'error',
|
|
17
15
|
};
|
|
18
16
|
class SentrySharedService {
|
|
19
17
|
constructor(sentryServiceCfg) {
|
|
@@ -35,8 +35,6 @@ function redact(redactPaths, obj, error) {
|
|
|
35
35
|
.map(path => (0, js_lib_1._get)(obj, path))
|
|
36
36
|
.filter(Boolean)
|
|
37
37
|
.forEach(secret => {
|
|
38
|
-
|
|
39
|
-
error.message = error.message.replace(secret, REDACTED);
|
|
40
|
-
}
|
|
38
|
+
error.message = error.message.replace(secret, REDACTED);
|
|
41
39
|
});
|
|
42
40
|
}
|
|
@@ -14,12 +14,12 @@ function serverStatusMiddleware(projectDir, extra) {
|
|
|
14
14
|
exports.serverStatusMiddleware = serverStatusMiddleware;
|
|
15
15
|
function getServerStatusData(projectDir = process.cwd(), extra) {
|
|
16
16
|
const { gitRev, gitBranch, prod, ts } = (0, deployInfo_util_1.getDeployInfo)(projectDir);
|
|
17
|
-
const t = (0, js_lib_1.localTime)(ts)
|
|
18
|
-
const
|
|
17
|
+
const t = (0, js_lib_1.localTime)(ts);
|
|
18
|
+
const deployBuildTime = t.toPretty();
|
|
19
19
|
const buildInfo = [t.toStringCompact(), gitBranch, gitRev].filter(Boolean).join('_');
|
|
20
20
|
return (0, js_lib_1._filterFalsyValues)({
|
|
21
21
|
started: getStartedStr(),
|
|
22
|
-
|
|
22
|
+
deployBuildTime,
|
|
23
23
|
APP_ENV,
|
|
24
24
|
prod,
|
|
25
25
|
buildInfo,
|
|
@@ -35,6 +35,6 @@ function getServerStatusData(projectDir = process.cwd(), extra) {
|
|
|
35
35
|
}
|
|
36
36
|
exports.getServerStatusData = getServerStatusData;
|
|
37
37
|
function getStartedStr() {
|
|
38
|
-
const started = (0, js_lib_1.localTime)().
|
|
39
|
-
return `${started.toPretty()}
|
|
38
|
+
const started = (0, js_lib_1.localTime)().subtract(process.uptime(), 'second');
|
|
39
|
+
return `${started.toPretty()} (${started.fromNow()})`;
|
|
40
40
|
}
|
|
@@ -52,8 +52,6 @@ function redact(redactPaths, obj, error) {
|
|
|
52
52
|
.map(path => (0, js_lib_1._get)(obj, path))
|
|
53
53
|
.filter(Boolean)
|
|
54
54
|
.forEach(secret => {
|
|
55
|
-
|
|
56
|
-
error.message = error.message.replace(secret, REDACTED);
|
|
57
|
-
}
|
|
55
|
+
error.message = error.message.replace(secret, REDACTED);
|
|
58
56
|
});
|
|
59
57
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install && patch-package",
|
|
6
6
|
"serve": "APP_ENV=dev nodemon",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"deploy-health-check-debug2": "yarn tsn ./src/bin/deploy-health-check.ts --url https://api-master2.naturalcycles.com --thresholdUnhealthy 5"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@sentry/node": "^
|
|
16
|
+
"@sentry/node": "^7.0.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@naturalcycles/db-lib": "^8.0.2",
|
|
@@ -39,14 +39,13 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@naturalcycles/bench-lib": "^1.0.7",
|
|
42
|
-
"@naturalcycles/dev-lib": "^
|
|
43
|
-
"@sentry/node": "^
|
|
42
|
+
"@naturalcycles/dev-lib": "^13.0.0",
|
|
43
|
+
"@sentry/node": "^7.0.0",
|
|
44
44
|
"@types/ejs": "^3.0.0",
|
|
45
45
|
"@types/js-yaml": "^4.0.0",
|
|
46
46
|
"@types/node": "^17.0.0",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"jest": "^27.0.1",
|
|
47
|
+
"fastify": "^4.0.0",
|
|
48
|
+
"jest": "^28.0.3",
|
|
50
49
|
"nodemon": "^2.0.14",
|
|
51
50
|
"patch-package": "^6.2.1",
|
|
52
51
|
"prettier": "^2.0.0",
|
package/src/db/httpDB.ts
CHANGED
|
@@ -92,10 +92,10 @@ export class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
92
92
|
.json()
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
override async saveBatch<ROW extends ObjectWithId
|
|
95
|
+
override async saveBatch<ROW extends Partial<ObjectWithId>>(
|
|
96
96
|
table: string,
|
|
97
97
|
rows: ROW[],
|
|
98
|
-
opt?: CommonDBSaveOptions
|
|
98
|
+
opt?: CommonDBSaveOptions<ROW>,
|
|
99
99
|
): Promise<void> {
|
|
100
100
|
await this.got.put(`saveBatch`, {
|
|
101
101
|
json: {
|
|
@@ -43,7 +43,7 @@ export async function createDeployInfo(backendCfg: BackendCfg): Promise<DeployIn
|
|
|
43
43
|
const simpleGit = require('simple-git/promise') as typeof simpleGitLib // lazy load
|
|
44
44
|
const git = simpleGit('.')
|
|
45
45
|
|
|
46
|
-
const now = localTime()
|
|
46
|
+
const now = localTime()
|
|
47
47
|
const gitBranch = (await git.status()).current!
|
|
48
48
|
const gitRev = (await git.revparse(['HEAD'])).slice(0, 7)
|
|
49
49
|
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { _anyToError, _Memo, CommonLogger, CommonLogLevel } from '@naturalcycles/js-lib'
|
|
2
2
|
import { inspectAny, inspectAnyStringifyFn } from '@naturalcycles/nodejs-lib'
|
|
3
|
-
import {
|
|
4
|
-
import type { Breadcrumb, NodeOptions } from '@sentry/node'
|
|
3
|
+
import type { Breadcrumb, NodeOptions, SeverityLevel } from '@sentry/node'
|
|
5
4
|
import type * as SentryLib from '@sentry/node'
|
|
6
5
|
import { BackendErrorRequestHandler, BackendRequestHandler, getRequestLogger } from '../index'
|
|
7
6
|
|
|
8
7
|
export interface SentrySharedServiceCfg extends NodeOptions {}
|
|
9
8
|
|
|
10
|
-
const sentrySeverityMap: Record<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
[Severity.Fatal]: 'error',
|
|
9
|
+
const sentrySeverityMap: Record<SeverityLevel, CommonLogLevel> = {
|
|
10
|
+
debug: 'log',
|
|
11
|
+
info: 'log',
|
|
12
|
+
log: 'log',
|
|
13
|
+
warning: 'warn',
|
|
14
|
+
error: 'error',
|
|
15
|
+
fatal: 'error',
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
export class SentrySharedService {
|
|
@@ -106,7 +104,7 @@ export class SentrySharedService {
|
|
|
106
104
|
/**
|
|
107
105
|
* Returns "eventId"
|
|
108
106
|
*/
|
|
109
|
-
captureMessage(msg: string, level?:
|
|
107
|
+
captureMessage(msg: string, level?: SeverityLevel): string {
|
|
110
108
|
getRequestLogger()[sentrySeverityMap[level!] || 'log']('captureMessage:', msg)
|
|
111
109
|
return this.sentry().captureMessage(msg, level)
|
|
112
110
|
}
|
|
@@ -59,8 +59,6 @@ function redact(redactPaths: string[], obj: any, error: Error): void {
|
|
|
59
59
|
.map(path => _get(obj, path))
|
|
60
60
|
.filter(Boolean)
|
|
61
61
|
.forEach(secret => {
|
|
62
|
-
|
|
63
|
-
error.message = error.message.replace(secret, REDACTED)
|
|
64
|
-
}
|
|
62
|
+
error.message = error.message.replace(secret, REDACTED)
|
|
65
63
|
})
|
|
66
64
|
}
|
|
@@ -72,7 +72,7 @@ export function requestTimeoutMiddleware(
|
|
|
72
72
|
)
|
|
73
73
|
}, timeoutSeconds * 1000)
|
|
74
74
|
|
|
75
|
-
onFinished(res, () => clearTimeout(req.requestTimeout
|
|
75
|
+
onFinished(res, () => clearTimeout(req.requestTimeout))
|
|
76
76
|
|
|
77
77
|
next()
|
|
78
78
|
}
|
|
@@ -110,7 +110,7 @@ export function customRequestTimeoutMiddleware(
|
|
|
110
110
|
}
|
|
111
111
|
}, timeoutSeconds * 1000)
|
|
112
112
|
|
|
113
|
-
onFinished(res, () => clearTimeout(req.requestTimeout
|
|
113
|
+
onFinished(res, () => clearTimeout(req.requestTimeout))
|
|
114
114
|
|
|
115
115
|
next()
|
|
116
116
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Server } from 'http'
|
|
2
|
+
import { Socket } from 'net'
|
|
3
|
+
import { StringMap } from '@naturalcycles/js-lib'
|
|
2
4
|
|
|
3
5
|
export interface DestroyableServer extends Server {
|
|
4
6
|
destroy(): Promise<void>
|
|
@@ -10,7 +12,7 @@ export interface DestroyableServer extends Server {
|
|
|
10
12
|
* @experimental
|
|
11
13
|
*/
|
|
12
14
|
export function enableDestroy(server: Server): DestroyableServer {
|
|
13
|
-
const connections = {}
|
|
15
|
+
const connections: StringMap<Socket> = {}
|
|
14
16
|
const srv = server as DestroyableServer
|
|
15
17
|
|
|
16
18
|
srv.on('connection', function (conn) {
|
|
@@ -23,7 +25,7 @@ export function enableDestroy(server: Server): DestroyableServer {
|
|
|
23
25
|
// let started = Date.now()
|
|
24
26
|
const p = new Promise(resolve => server.close(resolve))
|
|
25
27
|
for (const key of Object.keys(connections)) {
|
|
26
|
-
connections[key]
|
|
28
|
+
connections[key]!.destroy()
|
|
27
29
|
}
|
|
28
30
|
await p
|
|
29
31
|
// console.log(`destroyed ${Object.keys(connections).length} con(s) in ${_since(started)}`)
|
|
@@ -31,7 +31,7 @@ interface Stat {
|
|
|
31
31
|
const serverStatsMap: StringMap<Stat> = {}
|
|
32
32
|
|
|
33
33
|
const percentiles = [50, 90, 99]
|
|
34
|
-
const families = ['2xx', '4xx', '5xx']
|
|
34
|
+
const families: (keyof Stat)[] = ['2xx', '4xx', '5xx']
|
|
35
35
|
|
|
36
36
|
// Store this number of last latencies
|
|
37
37
|
const SIZE = 50
|
|
@@ -17,13 +17,13 @@ export function getServerStatusData(
|
|
|
17
17
|
extra?: any,
|
|
18
18
|
): Record<string, any> {
|
|
19
19
|
const { gitRev, gitBranch, prod, ts } = getDeployInfo(projectDir)
|
|
20
|
-
const t = localTime(ts)
|
|
21
|
-
const
|
|
20
|
+
const t = localTime(ts)
|
|
21
|
+
const deployBuildTime = t.toPretty()
|
|
22
22
|
const buildInfo = [t.toStringCompact(), gitBranch, gitRev].filter(Boolean).join('_')
|
|
23
23
|
|
|
24
24
|
return _filterFalsyValues({
|
|
25
25
|
started: getStartedStr(),
|
|
26
|
-
|
|
26
|
+
deployBuildTime,
|
|
27
27
|
APP_ENV,
|
|
28
28
|
prod,
|
|
29
29
|
buildInfo,
|
|
@@ -39,6 +39,6 @@ export function getServerStatusData(
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
function getStartedStr(): string {
|
|
42
|
-
const started = localTime().
|
|
43
|
-
return `${started.toPretty()}
|
|
42
|
+
const started = localTime().subtract(process.uptime(), 'second')
|
|
43
|
+
return `${started.toPretty()} (${started.fromNow()})`
|
|
44
44
|
}
|
|
@@ -74,8 +74,6 @@ function redact(redactPaths: string[], obj: any, error: Error): void {
|
|
|
74
74
|
.map(path => _get(obj, path))
|
|
75
75
|
.filter(Boolean)
|
|
76
76
|
.forEach(secret => {
|
|
77
|
-
|
|
78
|
-
error.message = error.message.replace(secret, REDACTED)
|
|
79
|
-
}
|
|
77
|
+
error.message = error.message.replace(secret, REDACTED)
|
|
80
78
|
})
|
|
81
79
|
}
|