@naturalcycles/backend-lib 4.18.6 → 4.18.8
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/base.admin.service.js +4 -4
- package/dist/bin/deploy-gae.js +2 -2
- package/dist/bin/deploy-health-check.js +2 -2
- package/dist/bin/deploy-prepare.js +2 -2
- package/dist/db/httpDB.d.ts +5 -5
- package/dist/db/httpDB.js +17 -27
- package/dist/deploy/deploy.util.js +7 -7
- package/dist/deploy/deployHealthCheck.js +5 -5
- package/dist/deploy/deployPrepare.js +6 -6
- package/dist/env/env.shared.service.js +3 -3
- package/dist/server/appEngineLogMiddleware.js +4 -4
- package/dist/server/request.log.util.js +5 -5
- package/dist/server/simpleRequestLoggerMiddleware.js +3 -3
- package/dist/server/startServer.js +6 -6
- package/dist/testing/express.test.service.d.ts +5 -5
- package/dist/testing/express.test.service.js +20 -9
- package/package.json +2 -2
- package/src/admin/base.admin.service.ts +1 -1
- package/src/bin/deploy-gae.ts +1 -1
- package/src/bin/deploy-health-check.ts +1 -1
- package/src/bin/deploy-prepare.ts +1 -1
- package/src/db/httpDB.ts +49 -53
- package/src/deploy/deploy.util.ts +1 -1
- package/src/deploy/deployHealthCheck.ts +1 -1
- package/src/deploy/deployPrepare.ts +2 -2
- package/src/env/env.shared.service.ts +1 -1
- package/src/server/appEngineLogMiddleware.ts +1 -1
- package/src/server/request.log.util.ts +1 -1
- package/src/server/simpleRequestLoggerMiddleware.ts +1 -1
- package/src/server/startServer.ts +1 -1
- package/src/testing/express.test.service.ts +32 -13
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BaseAdminService = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const
|
|
5
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const adminInfoDisabled = () => ({
|
|
7
7
|
email: 'authDisabled',
|
|
8
8
|
permissions: [],
|
|
@@ -35,7 +35,7 @@ class BaseAdminService {
|
|
|
35
35
|
getEmailPermissions(email) {
|
|
36
36
|
if (!email)
|
|
37
37
|
return;
|
|
38
|
-
console.log(`getEmailPermissions (${(0,
|
|
38
|
+
console.log(`getEmailPermissions (${(0, nodejs_lib_1.dimGrey)(email)}) returning undefined (please override the implementation)`);
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -43,7 +43,7 @@ class BaseAdminService {
|
|
|
43
43
|
*/
|
|
44
44
|
// eslint-disable-next-line max-params
|
|
45
45
|
async onPermissionCheck(req, email, reqPermissions, required, granted, meta = {}) {
|
|
46
|
-
req.log(`${(0,
|
|
46
|
+
req.log(`${(0, nodejs_lib_1.dimGrey)(email)} ${required ? 'required' : 'optional'} permissions check [${(0, nodejs_lib_1.dimGrey)(reqPermissions.join(', '))}]: ${granted ? (0, nodejs_lib_1.green)('GRANTED') : (0, nodejs_lib_1.red)('DENIED')}`, meta);
|
|
47
47
|
}
|
|
48
48
|
async getEmailByToken(req, adminToken) {
|
|
49
49
|
if (!adminToken)
|
|
@@ -51,7 +51,7 @@ class BaseAdminService {
|
|
|
51
51
|
try {
|
|
52
52
|
const decodedToken = await this.firebaseAuth.verifyIdToken(adminToken);
|
|
53
53
|
const email = decodedToken?.email;
|
|
54
|
-
req.log(`admin email: ${(0,
|
|
54
|
+
req.log(`admin email: ${(0, nodejs_lib_1.dimGrey)(email)}`);
|
|
55
55
|
return email;
|
|
56
56
|
}
|
|
57
57
|
catch (err) {
|
package/dist/bin/deploy-gae.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
const
|
|
4
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
5
|
const yargs = require("yargs");
|
|
6
6
|
const deployGae_1 = require("../deploy/deployGae");
|
|
7
7
|
const deployHealthCheck_1 = require("../deploy/deployHealthCheck");
|
|
8
8
|
const deployPrepare_1 = require("../deploy/deployPrepare");
|
|
9
|
-
(0,
|
|
9
|
+
(0, nodejs_lib_1.runScript)(async () => {
|
|
10
10
|
const opt = yargs.options({
|
|
11
11
|
...deployPrepare_1.deployPrepareYargsOptions,
|
|
12
12
|
...deployHealthCheck_1.deployHealthCheckYargsOptions,
|
|
@@ -9,10 +9,10 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
|
9
9
|
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const
|
|
12
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
13
13
|
const yargs = require("yargs");
|
|
14
14
|
const deployHealthCheck_1 = require("../deploy/deployHealthCheck");
|
|
15
|
-
(0,
|
|
15
|
+
(0, nodejs_lib_1.runScript)(async () => {
|
|
16
16
|
const { url, ...opt } = yargs.options({
|
|
17
17
|
...deployHealthCheck_1.deployHealthCheckYargsOptions,
|
|
18
18
|
url: {
|
|
@@ -6,10 +6,10 @@ yarn deploy-prepare
|
|
|
6
6
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
const
|
|
9
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
10
10
|
const yargs = require("yargs");
|
|
11
11
|
const deployPrepare_1 = require("../deploy/deployPrepare");
|
|
12
|
-
(0,
|
|
12
|
+
(0, nodejs_lib_1.runScript)(async () => {
|
|
13
13
|
const opt = yargs.options(deployPrepare_1.deployPrepareYargsOptions).argv;
|
|
14
14
|
await (0, deployPrepare_1.deployPrepare)(opt);
|
|
15
15
|
});
|
package/dist/db/httpDB.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
1
|
+
import { FetcherOptions, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
2
2
|
import { BaseCommonDB, CommonDB, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, DBQuery, RunQueryResult } from '@naturalcycles/db-lib';
|
|
3
|
-
import {
|
|
4
|
-
export interface HttpDBCfg extends
|
|
5
|
-
|
|
3
|
+
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
|
+
export interface HttpDBCfg extends FetcherOptions {
|
|
5
|
+
baseUrl: string;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Implementation of CommonDB that proxies all requests via HTTP to "httpDBRequestHandler".
|
|
@@ -11,7 +11,7 @@ export declare class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
11
11
|
cfg: HttpDBCfg;
|
|
12
12
|
constructor(cfg: HttpDBCfg);
|
|
13
13
|
setCfg(cfg: HttpDBCfg): void;
|
|
14
|
-
private
|
|
14
|
+
private fetcher;
|
|
15
15
|
ping(): Promise<void>;
|
|
16
16
|
getTables(): Promise<string[]>;
|
|
17
17
|
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
package/dist/db/httpDB.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HttpDB = void 0;
|
|
4
4
|
const node_stream_1 = require("node:stream");
|
|
5
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
6
|
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
6
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
7
7
|
/**
|
|
8
8
|
* Implementation of CommonDB that proxies all requests via HTTP to "httpDBRequestHandler".
|
|
9
9
|
*/
|
|
@@ -14,53 +14,47 @@ class HttpDB extends db_lib_1.BaseCommonDB {
|
|
|
14
14
|
this.setCfg(cfg);
|
|
15
15
|
}
|
|
16
16
|
setCfg(cfg) {
|
|
17
|
-
this.
|
|
17
|
+
this.fetcher = (0, js_lib_1.getFetcher)(cfg);
|
|
18
18
|
}
|
|
19
19
|
async ping() {
|
|
20
|
-
await this.
|
|
20
|
+
await this.fetcher.getVoid(`ping`);
|
|
21
21
|
}
|
|
22
22
|
async getTables() {
|
|
23
|
-
return await this.
|
|
23
|
+
return await this.fetcher.get(`tables`);
|
|
24
24
|
}
|
|
25
25
|
async getTableSchema(table) {
|
|
26
|
-
return await this.
|
|
26
|
+
return await this.fetcher.get(`${table}/schema`);
|
|
27
27
|
}
|
|
28
28
|
async resetCache(table = '') {
|
|
29
|
-
await this.
|
|
29
|
+
await this.fetcher.putVoid(`resetCache/${table}`);
|
|
30
30
|
}
|
|
31
31
|
async getByIds(table, ids, opt) {
|
|
32
|
-
return await this.
|
|
33
|
-
.put(`getByIds`, {
|
|
32
|
+
return await this.fetcher.put(`getByIds`, {
|
|
34
33
|
json: {
|
|
35
34
|
table,
|
|
36
35
|
ids,
|
|
37
36
|
opt,
|
|
38
37
|
},
|
|
39
|
-
})
|
|
40
|
-
.json();
|
|
38
|
+
});
|
|
41
39
|
}
|
|
42
40
|
async runQuery(query, opt) {
|
|
43
|
-
return await this.
|
|
44
|
-
.put(`runQuery`, {
|
|
41
|
+
return await this.fetcher.put(`runQuery`, {
|
|
45
42
|
json: {
|
|
46
43
|
query,
|
|
47
44
|
opt,
|
|
48
45
|
},
|
|
49
|
-
})
|
|
50
|
-
.json();
|
|
46
|
+
});
|
|
51
47
|
}
|
|
52
48
|
async runQueryCount(query, opt) {
|
|
53
|
-
return await this.
|
|
54
|
-
.put(`runQueryCount`, {
|
|
49
|
+
return await this.fetcher.put(`runQueryCount`, {
|
|
55
50
|
json: {
|
|
56
51
|
query,
|
|
57
52
|
opt,
|
|
58
53
|
},
|
|
59
|
-
})
|
|
60
|
-
.json();
|
|
54
|
+
});
|
|
61
55
|
}
|
|
62
56
|
async saveBatch(table, rows, opt) {
|
|
63
|
-
await this.
|
|
57
|
+
await this.fetcher.putVoid(`saveBatch`, {
|
|
64
58
|
json: {
|
|
65
59
|
table,
|
|
66
60
|
rows,
|
|
@@ -69,25 +63,21 @@ class HttpDB extends db_lib_1.BaseCommonDB {
|
|
|
69
63
|
});
|
|
70
64
|
}
|
|
71
65
|
async deleteByIds(table, ids, opt) {
|
|
72
|
-
return await this.
|
|
73
|
-
.put(`deleteByIds`, {
|
|
66
|
+
return await this.fetcher.put(`deleteByIds`, {
|
|
74
67
|
json: {
|
|
75
68
|
table,
|
|
76
69
|
ids,
|
|
77
70
|
opt,
|
|
78
71
|
},
|
|
79
|
-
})
|
|
80
|
-
.json();
|
|
72
|
+
});
|
|
81
73
|
}
|
|
82
74
|
async deleteByQuery(query, opt) {
|
|
83
|
-
return await this.
|
|
84
|
-
.put(`deleteByQuery`, {
|
|
75
|
+
return await this.fetcher.put(`deleteByQuery`, {
|
|
85
76
|
json: {
|
|
86
77
|
query,
|
|
87
78
|
opt,
|
|
88
79
|
},
|
|
89
|
-
})
|
|
90
|
-
.json();
|
|
80
|
+
});
|
|
91
81
|
}
|
|
92
82
|
streamQuery(_q, _opt) {
|
|
93
83
|
console.warn(`streamQuery not implemented`);
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validateGAEServiceName = exports.createAppYaml = exports.createAndSaveAppYaml = exports.createDeployInfo = exports.createAndSaveDeployInfo = void 0;
|
|
4
4
|
const fs = require("node:fs");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
const
|
|
6
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
7
7
|
const yaml = require("js-yaml");
|
|
8
8
|
const APP_YAML_DEFAULT = () => ({
|
|
9
9
|
runtime: 'nodejs18',
|
|
@@ -27,7 +27,7 @@ async function createAndSaveDeployInfo(backendCfg, targetDir) {
|
|
|
27
27
|
const deployInfo = await createDeployInfo(backendCfg);
|
|
28
28
|
const deployInfoPath = `${targetDir}/deployInfo.json`;
|
|
29
29
|
fs.writeFileSync(deployInfoPath, JSON.stringify(deployInfo, null, 2));
|
|
30
|
-
console.log(`saved ${(0,
|
|
30
|
+
console.log(`saved ${(0, nodejs_lib_1.dimGrey)(deployInfoPath)}`);
|
|
31
31
|
return deployInfo;
|
|
32
32
|
}
|
|
33
33
|
exports.createAndSaveDeployInfo = createAndSaveDeployInfo;
|
|
@@ -74,7 +74,7 @@ function createAndSaveAppYaml(backendCfg, deployInfo, projectDir, targetDir, app
|
|
|
74
74
|
const appYaml = createAppYaml(backendCfg, deployInfo, projectDir, appYamlPassEnv);
|
|
75
75
|
const appYamlPath = `${targetDir}/app.yaml`;
|
|
76
76
|
fs.writeFileSync(appYamlPath, yaml.dump(appYaml));
|
|
77
|
-
console.log(`saved ${(0,
|
|
77
|
+
console.log(`saved ${(0, nodejs_lib_1.dimGrey)(appYamlPath)}`);
|
|
78
78
|
return appYaml;
|
|
79
79
|
}
|
|
80
80
|
exports.createAndSaveAppYaml = createAndSaveAppYaml;
|
|
@@ -84,18 +84,18 @@ function createAppYaml(backendCfg, deployInfo, projectDir, appYamlPassEnv = '')
|
|
|
84
84
|
const { APP_ENV: processAppEnv } = process.env;
|
|
85
85
|
const APP_ENV = processAppEnv || appEnvByBranch[gitBranch] || appEnvDefault;
|
|
86
86
|
if (processAppEnv) {
|
|
87
|
-
console.log(`using APP_ENV=${(0,
|
|
87
|
+
console.log(`using APP_ENV=${(0, nodejs_lib_1.dimGrey)(processAppEnv)} from process.env`);
|
|
88
88
|
}
|
|
89
89
|
const appYaml = APP_YAML_DEFAULT();
|
|
90
90
|
// Check existing app.yaml
|
|
91
91
|
const appYamlPath = `${projectDir}/app.yaml`;
|
|
92
92
|
if (fs.existsSync(appYamlPath)) {
|
|
93
|
-
console.log(`merging-in ${(0,
|
|
93
|
+
console.log(`merging-in ${(0, nodejs_lib_1.dimGrey)(appYamlPath)}`);
|
|
94
94
|
(0, js_lib_1._merge)(appYaml, yaml.load(fs.readFileSync(appYamlPath, 'utf8')));
|
|
95
95
|
}
|
|
96
96
|
const appEnvYamlPath = `${projectDir}/app.${APP_ENV}.yaml`;
|
|
97
97
|
if (fs.existsSync(appEnvYamlPath)) {
|
|
98
|
-
console.log(`merging-in ${(0,
|
|
98
|
+
console.log(`merging-in ${(0, nodejs_lib_1.dimGrey)(appEnvYamlPath)}`);
|
|
99
99
|
(0, js_lib_1._merge)(appYaml, yaml.load(fs.readFileSync(appEnvYamlPath, 'utf8')));
|
|
100
100
|
}
|
|
101
101
|
// appYamlPassEnv
|
|
@@ -113,7 +113,7 @@ function createAppYaml(backendCfg, deployInfo, projectDir, appYamlPassEnv = '')
|
|
|
113
113
|
return map;
|
|
114
114
|
}, {});
|
|
115
115
|
if (Object.keys(passEnv).length) {
|
|
116
|
-
console.log(`will merge ${(0,
|
|
116
|
+
console.log(`will merge ${(0, nodejs_lib_1.white)(String(Object.keys(passEnv).length))} process.env keys to app.yaml: ${(0, nodejs_lib_1.dimGrey)(Object.keys(passEnv).join(', '))}`);
|
|
117
117
|
}
|
|
118
118
|
(0, js_lib_1._merge)(appYaml, {
|
|
119
119
|
service,
|
|
@@ -4,7 +4,7 @@ exports.deployHealthCheck = exports.deployHealthCheckYargsOptions = void 0;
|
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
7
|
-
const
|
|
7
|
+
const nodejs_lib_2 = require("@naturalcycles/nodejs-lib");
|
|
8
8
|
const request_log_util_1 = require("../server/request.log.util");
|
|
9
9
|
exports.deployHealthCheckYargsOptions = {
|
|
10
10
|
thresholdHealthy: {
|
|
@@ -70,7 +70,7 @@ async function deployHealthCheck(url, opt = {}) {
|
|
|
70
70
|
await makeAttempt();
|
|
71
71
|
}
|
|
72
72
|
if (failed) {
|
|
73
|
-
console.log((0,
|
|
73
|
+
console.log((0, nodejs_lib_2.red)(`Health check failed!`));
|
|
74
74
|
if (logOnFailure) {
|
|
75
75
|
try {
|
|
76
76
|
(0, nodejs_lib_1.execVoidCommandSync)(`gcloud app logs read --project ${gaeProject} --service ${gaeService} --version ${gaeVersion}`, [], { shell: true });
|
|
@@ -87,7 +87,7 @@ async function deployHealthCheck(url, opt = {}) {
|
|
|
87
87
|
}
|
|
88
88
|
async function makeAttempt() {
|
|
89
89
|
attempt++;
|
|
90
|
-
console.log([`>>`, (0,
|
|
90
|
+
console.log([`>>`, (0, nodejs_lib_2.dimGrey)(url), (0, node_util_1.inspect)({ attempt }, inspectOpt)].join(' '));
|
|
91
91
|
const started = Date.now();
|
|
92
92
|
const { err, statusCode = 0 } = await fetcher.doFetch({
|
|
93
93
|
url,
|
|
@@ -123,7 +123,7 @@ async function deployHealthCheck(url, opt = {}) {
|
|
|
123
123
|
console.log([
|
|
124
124
|
`<< HTTP`,
|
|
125
125
|
(0, request_log_util_1.coloredHttpCode)(statusCode),
|
|
126
|
-
(0,
|
|
126
|
+
(0, nodejs_lib_2.dimGrey)((0, js_lib_1._since)(started)),
|
|
127
127
|
(0, node_util_1.inspect)((0, js_lib_1._filterFalsyValues)({ countHealthy, countUnhealthy }), inspectOpt),
|
|
128
128
|
].join(' '));
|
|
129
129
|
if (attempt >= maxTries) {
|
|
@@ -135,7 +135,7 @@ async function deployHealthCheck(url, opt = {}) {
|
|
|
135
135
|
console.log(doneReason);
|
|
136
136
|
}
|
|
137
137
|
else {
|
|
138
|
-
console.log((0,
|
|
138
|
+
console.log((0, nodejs_lib_2.dimGrey)(`... waiting ${(0, js_lib_1._ms)(currentInterval)} ...`));
|
|
139
139
|
await (0, js_lib_1.pDelay)(currentInterval);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deployPrepare = exports.deployPrepareYargsOptions = void 0;
|
|
4
4
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const nodejs_lib_2 = require("@naturalcycles/nodejs-lib");
|
|
6
|
+
const nodejs_lib_3 = require("@naturalcycles/nodejs-lib");
|
|
7
7
|
const paths_cnst_1 = require("../paths.cnst");
|
|
8
8
|
const backend_cfg_util_1 = require("./backend.cfg.util");
|
|
9
9
|
const deploy_util_1 = require("./deploy.util");
|
|
@@ -58,15 +58,15 @@ async function deployPrepare(opt = {}) {
|
|
|
58
58
|
const backendCfg = (0, backend_cfg_util_1.getBackendCfg)(projectDir);
|
|
59
59
|
const inputPatterns = backendCfg.files || DEFAULT_FILES;
|
|
60
60
|
const appYamlPassEnv = opt.appYamlPassEnv || backendCfg.appYamlPassEnv;
|
|
61
|
-
console.log(`1. Copy files to ${(0,
|
|
61
|
+
console.log(`1. Copy files to ${(0, nodejs_lib_2.dimGrey)(targetDir)}`);
|
|
62
62
|
// Clean targetDir
|
|
63
63
|
(0, nodejs_lib_1._emptyDirSync)(targetDir);
|
|
64
|
-
(0,
|
|
64
|
+
(0, nodejs_lib_3.kpySync)({
|
|
65
65
|
baseDir: defaultFilesDir,
|
|
66
66
|
outputDir: targetDir,
|
|
67
67
|
dotfiles: true,
|
|
68
68
|
});
|
|
69
|
-
(0,
|
|
69
|
+
(0, nodejs_lib_3.kpySync)({
|
|
70
70
|
baseDir: projectDir,
|
|
71
71
|
inputPatterns,
|
|
72
72
|
outputDir: targetDir,
|
|
@@ -78,7 +78,7 @@ async function deployPrepare(opt = {}) {
|
|
|
78
78
|
const npmrc = `//registry.npmjs.org/:_authToken=${NPM_TOKEN}`;
|
|
79
79
|
(0, nodejs_lib_1._writeFileSync)(npmrcPath, npmrc);
|
|
80
80
|
}
|
|
81
|
-
console.log(`2. Generate ${(0,
|
|
81
|
+
console.log(`2. Generate ${(0, nodejs_lib_2.dimGrey)('deployInfo.json')} and ${(0, nodejs_lib_2.dimGrey)('app.yaml')} in targetDir`);
|
|
82
82
|
const deployInfo = await (0, deploy_util_1.createAndSaveDeployInfo)(backendCfg, targetDir);
|
|
83
83
|
(0, deploy_util_1.createAndSaveAppYaml)(backendCfg, deployInfo, projectDir, targetDir, appYamlPassEnv);
|
|
84
84
|
return deployInfo;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.EnvSharedService = void 0;
|
|
4
|
-
const
|
|
4
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
5
|
class EnvSharedService {
|
|
6
6
|
constructor(cfg) {
|
|
7
7
|
this.cfg = cfg;
|
|
@@ -24,12 +24,12 @@ class EnvSharedService {
|
|
|
24
24
|
catch {
|
|
25
25
|
throw new Error(`Cannot read envFile ${envFilePath}`);
|
|
26
26
|
}
|
|
27
|
-
console.log(`APP_ENV=${(0,
|
|
27
|
+
console.log(`APP_ENV=${(0, nodejs_lib_1.dimGrey)(APP_ENV)} loaded`);
|
|
28
28
|
}
|
|
29
29
|
return this.env;
|
|
30
30
|
}
|
|
31
31
|
setEnv(env) {
|
|
32
|
-
console.log(`setEnv APP_ENV=${(0,
|
|
32
|
+
console.log(`setEnv APP_ENV=${(0, nodejs_lib_1.dimGrey)(env ? env.name : 'undefined')}`);
|
|
33
33
|
this.env = env;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.appEngineLogMiddleware = exports.ciLogger = exports.devLogger = exports.gaeLogger = void 0;
|
|
4
4
|
const node_util_1 = require("node:util");
|
|
5
|
-
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
6
5
|
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
+
const nodejs_lib_2 = require("@naturalcycles/nodejs-lib");
|
|
7
7
|
const { GOOGLE_CLOUD_PROJECT, GAE_INSTANCE } = process.env;
|
|
8
8
|
const isGAE = !!GAE_INSTANCE;
|
|
9
9
|
// Simple "request counter" (poor man's "correlation id") counter, to use on dev machine (not in the cloud)
|
|
@@ -44,8 +44,8 @@ function logToAppEngine(meta, args) {
|
|
|
44
44
|
function logToDev(requestId, args) {
|
|
45
45
|
// Run on local machine
|
|
46
46
|
console.log([
|
|
47
|
-
requestId ? [(0,
|
|
48
|
-
...args.map(a => (0,
|
|
47
|
+
requestId ? [(0, nodejs_lib_1.dimGrey)(`[${requestId}]`)] : [],
|
|
48
|
+
...args.map(a => (0, nodejs_lib_2.inspectAny)(a, { includeErrorStack: true, colors: true })),
|
|
49
49
|
].join(' '));
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
@@ -53,7 +53,7 @@ function logToDev(requestId, args) {
|
|
|
53
53
|
* This is to not confuse e.g Sentry when it picks up messages with colors
|
|
54
54
|
*/
|
|
55
55
|
function logToCI(args) {
|
|
56
|
-
console.log(args.map(a => (0,
|
|
56
|
+
console.log(args.map(a => (0, nodejs_lib_2.inspectAny)(a, { includeErrorStack: true, colors: false })).join(' '));
|
|
57
57
|
}
|
|
58
58
|
function appEngineLogMiddleware() {
|
|
59
59
|
if (!isGAE || !GOOGLE_CLOUD_PROJECT) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.coloredHttpCode = exports.logRequest = void 0;
|
|
4
|
-
const
|
|
4
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
5
|
function logRequest(req, statusCode, ...tokens) {
|
|
6
|
-
req[logLevel(statusCode)]([coloredHttpCode(statusCode), req.method, (0,
|
|
6
|
+
req[logLevel(statusCode)]([coloredHttpCode(statusCode), req.method, (0, nodejs_lib_1.boldGrey)(req.url), ...tokens].join(' '));
|
|
7
7
|
}
|
|
8
8
|
exports.logRequest = logRequest;
|
|
9
9
|
function coloredHttpCode(statusCode) {
|
|
10
10
|
if (statusCode >= 200 && statusCode < 400)
|
|
11
|
-
return (0,
|
|
11
|
+
return (0, nodejs_lib_1.green)(statusCode);
|
|
12
12
|
if (statusCode >= 400 && statusCode < 500)
|
|
13
|
-
return (0,
|
|
14
|
-
return (0,
|
|
13
|
+
return (0, nodejs_lib_1.yellow)(statusCode);
|
|
14
|
+
return (0, nodejs_lib_1.red)(statusCode);
|
|
15
15
|
}
|
|
16
16
|
exports.coloredHttpCode = coloredHttpCode;
|
|
17
17
|
function logLevel(statusCode) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.simpleRequestLoggerMiddleware = void 0;
|
|
4
4
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const
|
|
5
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
6
|
const index_1 = require("../index");
|
|
7
7
|
const request_log_util_1 = require("./request.log.util");
|
|
8
8
|
const { APP_ENV } = process.env;
|
|
@@ -20,11 +20,11 @@ function simpleRequestLoggerMiddleware(_cfg = {}) {
|
|
|
20
20
|
return (req, res, next) => {
|
|
21
21
|
const started = Date.now();
|
|
22
22
|
if (logStart) {
|
|
23
|
-
req.log(['>>', req.method, (0,
|
|
23
|
+
req.log(['>>', req.method, (0, nodejs_lib_1.boldGrey)(req.url)].join(' '));
|
|
24
24
|
}
|
|
25
25
|
if (logFinish) {
|
|
26
26
|
(0, index_1.onFinished)(res, () => {
|
|
27
|
-
(0, request_log_util_1.logRequest)(req, res.statusCode, (0,
|
|
27
|
+
(0, request_log_util_1.logRequest)(req, res.statusCode, (0, nodejs_lib_1.dimGrey)((0, js_lib_1._since)(started)));
|
|
28
28
|
// Avoid logging twice. It was previously logged by genericErrorHandler
|
|
29
29
|
// if (res.__err) {
|
|
30
30
|
// logRequest(req, res.statusCode, dimGrey(_since(started)), inspectAny(res.__err))
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.startServer = exports.BackendServer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
const
|
|
6
|
+
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
7
7
|
const index_1 = require("../index");
|
|
8
8
|
const { NODE_OPTIONS, APP_ENV } = process.env;
|
|
9
9
|
class BackendServer {
|
|
@@ -45,8 +45,8 @@ class BackendServer {
|
|
|
45
45
|
address = `http://${addr.address}:${port}`;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
console.log((0,
|
|
49
|
-
console.log(`serverStarted on ${(0,
|
|
48
|
+
console.log((0, nodejs_lib_1.dimGrey)(`node ${process.version}, NODE_OPTIONS: ${NODE_OPTIONS || 'undefined'}, APP_ENV: ${APP_ENV || 'undefined'}`));
|
|
49
|
+
console.log(`serverStarted on ${(0, nodejs_lib_1.white)(address)} in ${(0, nodejs_lib_1.dimGrey)((0, js_lib_1._ms)(process.uptime() * 1000))}`);
|
|
50
50
|
return {
|
|
51
51
|
port,
|
|
52
52
|
server: this.server,
|
|
@@ -58,9 +58,9 @@ class BackendServer {
|
|
|
58
58
|
* Does `process.exit()` in the end.
|
|
59
59
|
*/
|
|
60
60
|
async stop(reason) {
|
|
61
|
-
console.log((0,
|
|
61
|
+
console.log((0, nodejs_lib_1.dimGrey)(`Server shutdown (${reason})...`));
|
|
62
62
|
const shutdownTimeout = setTimeout(() => {
|
|
63
|
-
console.log((0,
|
|
63
|
+
console.log((0, nodejs_lib_1.boldGrey)('Forceful shutdown after timeout'));
|
|
64
64
|
process.exit(0);
|
|
65
65
|
}, this.cfg.forceShutdownTimeout ?? 10000);
|
|
66
66
|
try {
|
|
@@ -69,7 +69,7 @@ class BackendServer {
|
|
|
69
69
|
this.cfg.onShutdown?.(),
|
|
70
70
|
]);
|
|
71
71
|
clearTimeout(shutdownTimeout);
|
|
72
|
-
console.log((0,
|
|
72
|
+
console.log((0, nodejs_lib_1.dimGrey)('Shutdown completed.'));
|
|
73
73
|
process.exit(0);
|
|
74
74
|
}
|
|
75
75
|
catch (err) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fetcher, FetcherOptions } from '@naturalcycles/js-lib';
|
|
2
2
|
import { BackendApplication, DefaultAppCfg } from '../index';
|
|
3
3
|
import { BackendRequestHandlerCfg } from '../server/createDefaultApp.model';
|
|
4
|
-
export interface ExpressApp extends
|
|
4
|
+
export interface ExpressApp extends Fetcher {
|
|
5
5
|
close: () => Promise<void>;
|
|
6
6
|
}
|
|
7
7
|
declare class ExpressTestService {
|
|
8
|
-
createAppFromResource(resource: BackendRequestHandlerCfg, opt?:
|
|
9
|
-
createAppFromResources(resources: BackendRequestHandlerCfg[], opt?:
|
|
10
|
-
createApp(app: BackendApplication, opt?:
|
|
8
|
+
createAppFromResource(resource: BackendRequestHandlerCfg, opt?: FetcherOptions, defaultAppCfg?: DefaultAppCfg): ExpressApp;
|
|
9
|
+
createAppFromResources(resources: BackendRequestHandlerCfg[], opt?: FetcherOptions): ExpressApp;
|
|
10
|
+
createApp(app: BackendApplication, opt?: FetcherOptions): 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.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.expressTestService = void 0;
|
|
4
|
-
const
|
|
4
|
+
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
5
|
const index_1 = require("../index");
|
|
6
|
+
const nativeFetchFn = async (url, init) => await globalThis.fetch(url, init);
|
|
6
7
|
// Example:
|
|
7
8
|
// const app = expressTestService.createApp([ debugResource ])
|
|
8
9
|
// afterAll(async () => {
|
|
@@ -23,21 +24,31 @@ class ExpressTestService {
|
|
|
23
24
|
createApp(app, opt) {
|
|
24
25
|
const server = this.createTestServer(app);
|
|
25
26
|
const { port } = server.address();
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
27
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
28
|
+
const fetcher = (0, js_lib_1.getFetcher)({
|
|
29
|
+
baseUrl,
|
|
29
30
|
responseType: 'json',
|
|
30
|
-
retry: 0,
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
retry: { count: 0 },
|
|
32
|
+
logRequest: true,
|
|
33
|
+
logResponse: true,
|
|
34
|
+
logWithBaseUrl: false,
|
|
35
|
+
fetchFn: nativeFetchFn,
|
|
33
36
|
...opt,
|
|
37
|
+
}).onAfterResponse(async () => {
|
|
38
|
+
// This "empty" hook exists to act like `await pDelay`,
|
|
39
|
+
// so tests using it can reply on `void someAnalyticsService.doSmth()` promises
|
|
40
|
+
// to be done by that time.
|
|
41
|
+
// Smart, huh?
|
|
42
|
+
await (0, js_lib_1.pDelay)();
|
|
34
43
|
});
|
|
35
|
-
|
|
44
|
+
fetcher.close = async () => {
|
|
45
|
+
const started = Date.now();
|
|
36
46
|
await new Promise(resolve => server.close(resolve));
|
|
47
|
+
console.log(`close took ${(0, js_lib_1._since)(started)}`); // todo: investigate why it takes ~5 seconds!
|
|
37
48
|
// server.destroy()
|
|
38
49
|
// await pDelay(1000)
|
|
39
50
|
};
|
|
40
|
-
return
|
|
51
|
+
return fetcher;
|
|
41
52
|
}
|
|
42
53
|
/**
|
|
43
54
|
* Creates a "Default Express App" with provided resources.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
|
-
"version": "4.18.
|
|
3
|
+
"version": "4.18.8",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"serve": "APP_ENV=dev nodemon",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@naturalcycles/db-lib": "^8.0.2",
|
|
20
20
|
"@naturalcycles/js-lib": "^14.27.0",
|
|
21
|
-
"@naturalcycles/nodejs-lib": "^
|
|
21
|
+
"@naturalcycles/nodejs-lib": "^13.1.0",
|
|
22
22
|
"@types/cookie-parser": "^1.4.1",
|
|
23
23
|
"@types/cors": "^2.8.4",
|
|
24
24
|
"@types/express": "^4.16.1",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _assert, AppError } from '@naturalcycles/js-lib'
|
|
2
|
-
import { dimGrey, green, red } from '@naturalcycles/nodejs-lib
|
|
2
|
+
import { dimGrey, green, red } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import type * as FirebaseAdmin from 'firebase-admin'
|
|
4
4
|
import { BackendRequest, BackendRequestHandler } from '../server/server.model'
|
|
5
5
|
|
package/src/bin/deploy-gae.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { runScript } from '@naturalcycles/nodejs-lib
|
|
3
|
+
import { runScript } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import * as yargs from 'yargs'
|
|
5
5
|
import { deployGae } from '../deploy/deployGae'
|
|
6
6
|
import { deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck'
|
|
@@ -9,7 +9,7 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
|
9
9
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { runScript } from '@naturalcycles/nodejs-lib
|
|
12
|
+
import { runScript } from '@naturalcycles/nodejs-lib'
|
|
13
13
|
import * as yargs from 'yargs'
|
|
14
14
|
import { deployHealthCheck, deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck'
|
|
15
15
|
|
|
@@ -6,7 +6,7 @@ yarn deploy-prepare
|
|
|
6
6
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { runScript } from '@naturalcycles/nodejs-lib
|
|
9
|
+
import { runScript } from '@naturalcycles/nodejs-lib'
|
|
10
10
|
import * as yargs from 'yargs'
|
|
11
11
|
import { deployPrepare, deployPrepareYargsOptions } from '../deploy/deployPrepare'
|
|
12
12
|
|
package/src/db/httpDB.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Fetcher,
|
|
4
|
+
FetcherOptions,
|
|
5
|
+
getFetcher,
|
|
6
|
+
JsonSchemaRootObject,
|
|
7
|
+
ObjectWithId,
|
|
8
|
+
} from '@naturalcycles/js-lib'
|
|
3
9
|
import {
|
|
4
10
|
BaseCommonDB,
|
|
5
11
|
CommonDB,
|
|
@@ -9,10 +15,10 @@ import {
|
|
|
9
15
|
DBQuery,
|
|
10
16
|
RunQueryResult,
|
|
11
17
|
} from '@naturalcycles/db-lib'
|
|
12
|
-
import {
|
|
18
|
+
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
13
19
|
|
|
14
|
-
export interface HttpDBCfg extends
|
|
15
|
-
|
|
20
|
+
export interface HttpDBCfg extends FetcherOptions {
|
|
21
|
+
baseUrl: string
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
/**
|
|
@@ -25,27 +31,27 @@ export class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
setCfg(cfg: HttpDBCfg): void {
|
|
28
|
-
this.
|
|
34
|
+
this.fetcher = getFetcher(cfg)
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
private
|
|
37
|
+
private fetcher!: Fetcher
|
|
32
38
|
|
|
33
39
|
override async ping(): Promise<void> {
|
|
34
|
-
await this.
|
|
40
|
+
await this.fetcher.getVoid(`ping`)
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
override async getTables(): Promise<string[]> {
|
|
38
|
-
return await this.
|
|
44
|
+
return await this.fetcher.get(`tables`)
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
override async getTableSchema<ROW extends ObjectWithId>(
|
|
42
48
|
table: string,
|
|
43
49
|
): Promise<JsonSchemaRootObject<ROW>> {
|
|
44
|
-
return await this.
|
|
50
|
+
return await this.fetcher.get(`${table}/schema`)
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
async resetCache(table = ''): Promise<void> {
|
|
48
|
-
await this.
|
|
54
|
+
await this.fetcher.putVoid(`resetCache/${table}`)
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
override async getByIds<ROW extends ObjectWithId>(
|
|
@@ -53,43 +59,37 @@ export class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
53
59
|
ids: ROW['id'][],
|
|
54
60
|
opt?: CommonDBOptions,
|
|
55
61
|
): Promise<ROW[]> {
|
|
56
|
-
return await this.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
})
|
|
64
|
-
.json()
|
|
62
|
+
return await this.fetcher.put(`getByIds`, {
|
|
63
|
+
json: {
|
|
64
|
+
table,
|
|
65
|
+
ids,
|
|
66
|
+
opt,
|
|
67
|
+
},
|
|
68
|
+
})
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
override async runQuery<ROW extends ObjectWithId>(
|
|
68
72
|
query: DBQuery<ROW>,
|
|
69
73
|
opt?: CommonDBOptions,
|
|
70
74
|
): Promise<RunQueryResult<ROW>> {
|
|
71
|
-
return await this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
})
|
|
78
|
-
.json()
|
|
75
|
+
return await this.fetcher.put(`runQuery`, {
|
|
76
|
+
json: {
|
|
77
|
+
query,
|
|
78
|
+
opt,
|
|
79
|
+
},
|
|
80
|
+
})
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
override async runQueryCount<ROW extends ObjectWithId>(
|
|
82
84
|
query: DBQuery<ROW>,
|
|
83
85
|
opt?: CommonDBOptions,
|
|
84
86
|
): Promise<number> {
|
|
85
|
-
return await this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
})
|
|
92
|
-
.json()
|
|
87
|
+
return await this.fetcher.put(`runQueryCount`, {
|
|
88
|
+
json: {
|
|
89
|
+
query,
|
|
90
|
+
opt,
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
override async saveBatch<ROW extends Partial<ObjectWithId>>(
|
|
@@ -97,7 +97,7 @@ export class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
97
97
|
rows: ROW[],
|
|
98
98
|
opt?: CommonDBSaveOptions<ROW>,
|
|
99
99
|
): Promise<void> {
|
|
100
|
-
await this.
|
|
100
|
+
await this.fetcher.putVoid(`saveBatch`, {
|
|
101
101
|
json: {
|
|
102
102
|
table,
|
|
103
103
|
rows,
|
|
@@ -107,29 +107,25 @@ export class HttpDB extends BaseCommonDB implements CommonDB {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
async deleteByIds(table: string, ids: string[], opt?: CommonDBOptions): Promise<number> {
|
|
110
|
-
return await this.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
})
|
|
118
|
-
.json()
|
|
110
|
+
return await this.fetcher.put(`deleteByIds`, {
|
|
111
|
+
json: {
|
|
112
|
+
table,
|
|
113
|
+
ids,
|
|
114
|
+
opt,
|
|
115
|
+
},
|
|
116
|
+
})
|
|
119
117
|
}
|
|
120
118
|
|
|
121
119
|
override async deleteByQuery<ROW extends ObjectWithId>(
|
|
122
120
|
query: DBQuery<ROW>,
|
|
123
121
|
opt?: CommonDBOptions,
|
|
124
122
|
): Promise<number> {
|
|
125
|
-
return await this.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
})
|
|
132
|
-
.json()
|
|
123
|
+
return await this.fetcher.put(`deleteByQuery`, {
|
|
124
|
+
json: {
|
|
125
|
+
query,
|
|
126
|
+
opt,
|
|
127
|
+
},
|
|
128
|
+
})
|
|
133
129
|
}
|
|
134
130
|
|
|
135
131
|
override streamQuery<ROW extends ObjectWithId>(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from 'node:fs'
|
|
2
2
|
import { _mapValues, _merge, _truncate, localTime } from '@naturalcycles/js-lib'
|
|
3
|
-
import { dimGrey, white } from '@naturalcycles/nodejs-lib
|
|
3
|
+
import { dimGrey, white } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import * as yaml from 'js-yaml'
|
|
5
5
|
import { BackendCfg } from './backend.cfg.util'
|
|
6
6
|
import { AppYaml, DeployInfo } from './deploy.model'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { inspect, InspectOptions } from 'node:util'
|
|
2
2
|
import { execVoidCommandSync } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { pDelay, _filterFalsyValues, _ms, _since, getFetcher } from '@naturalcycles/js-lib'
|
|
4
|
-
import { dimGrey, red } from '@naturalcycles/nodejs-lib
|
|
4
|
+
import { dimGrey, red } from '@naturalcycles/nodejs-lib'
|
|
5
5
|
import { coloredHttpCode } from '../server/request.log.util'
|
|
6
6
|
|
|
7
7
|
export interface DeployHealthCheckOptions {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _emptyDirSync, _writeFileSync } from '@naturalcycles/nodejs-lib'
|
|
2
|
-
import { dimGrey } from '@naturalcycles/nodejs-lib
|
|
3
|
-
import { kpySync } from '@naturalcycles/nodejs-lib
|
|
2
|
+
import { dimGrey } from '@naturalcycles/nodejs-lib'
|
|
3
|
+
import { kpySync } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import { srcDir } from '../paths.cnst'
|
|
5
5
|
import { getBackendCfg } from './backend.cfg.util'
|
|
6
6
|
import { DeployInfo } from './deploy.model'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { inspect } from 'node:util'
|
|
2
|
-
import { dimGrey } from '@naturalcycles/nodejs-lib
|
|
2
|
+
import { dimGrey } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { inspectAny } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import { AnyObject, CommonLogger } from '@naturalcycles/js-lib'
|
|
5
5
|
import { BackendRequestHandler } from './server.model'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommonLogLevel } from '@naturalcycles/js-lib'
|
|
2
|
-
import { boldGrey, green, red, yellow } from '@naturalcycles/nodejs-lib
|
|
2
|
+
import { boldGrey, green, red, yellow } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { BackendRequest } from './server.model'
|
|
4
4
|
|
|
5
5
|
export function logRequest(req: BackendRequest, statusCode: number, ...tokens: any[]): void {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _since } from '@naturalcycles/js-lib'
|
|
2
|
-
import { boldGrey, dimGrey } from '@naturalcycles/nodejs-lib
|
|
2
|
+
import { boldGrey, dimGrey } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { BackendRequestHandler, onFinished } from '../index'
|
|
4
4
|
import { logRequest } from './request.log.util'
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Server } from 'node:http'
|
|
2
2
|
import { _Memo, _ms } from '@naturalcycles/js-lib'
|
|
3
|
-
import { boldGrey, dimGrey, white } from '@naturalcycles/nodejs-lib
|
|
3
|
+
import { boldGrey, dimGrey, white } from '@naturalcycles/nodejs-lib'
|
|
4
4
|
import { createDefaultApp } from '../index'
|
|
5
5
|
import { StartServerCfg, StartServerData } from './startServer.model'
|
|
6
6
|
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { Server } from 'node:http'
|
|
2
2
|
import { AddressInfo } from 'node:net'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
_since,
|
|
5
|
+
Fetcher,
|
|
6
|
+
FetcherOptions,
|
|
7
|
+
FetchFunction,
|
|
8
|
+
getFetcher,
|
|
9
|
+
pDelay,
|
|
10
|
+
} from '@naturalcycles/js-lib'
|
|
4
11
|
import { BackendApplication, createDefaultApp, DefaultAppCfg } from '../index'
|
|
5
12
|
import { BackendRequestHandlerCfg } from '../server/createDefaultApp.model'
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
const nativeFetchFn: FetchFunction = async (url, init) => await globalThis.fetch(url, init)
|
|
15
|
+
|
|
16
|
+
export interface ExpressApp extends Fetcher {
|
|
8
17
|
close: () => Promise<void>
|
|
9
18
|
}
|
|
10
19
|
|
|
@@ -17,7 +26,7 @@ export interface ExpressApp extends Got {
|
|
|
17
26
|
class ExpressTestService {
|
|
18
27
|
createAppFromResource(
|
|
19
28
|
resource: BackendRequestHandlerCfg,
|
|
20
|
-
opt?:
|
|
29
|
+
opt?: FetcherOptions,
|
|
21
30
|
defaultAppCfg?: DefaultAppCfg,
|
|
22
31
|
): ExpressApp {
|
|
23
32
|
return this.createApp(
|
|
@@ -29,7 +38,7 @@ class ExpressTestService {
|
|
|
29
38
|
)
|
|
30
39
|
}
|
|
31
40
|
|
|
32
|
-
createAppFromResources(resources: BackendRequestHandlerCfg[], opt?:
|
|
41
|
+
createAppFromResources(resources: BackendRequestHandlerCfg[], opt?: FetcherOptions): ExpressApp {
|
|
33
42
|
return this.createApp(
|
|
34
43
|
createDefaultApp({
|
|
35
44
|
resources,
|
|
@@ -38,27 +47,37 @@ class ExpressTestService {
|
|
|
38
47
|
)
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
createApp(app: BackendApplication, opt?:
|
|
50
|
+
createApp(app: BackendApplication, opt?: FetcherOptions): ExpressApp {
|
|
42
51
|
const server = this.createTestServer(app)
|
|
43
52
|
const { port } = server.address() as AddressInfo
|
|
44
|
-
const
|
|
53
|
+
const baseUrl = `http://127.0.0.1:${port}`
|
|
45
54
|
|
|
46
|
-
const
|
|
47
|
-
|
|
55
|
+
const fetcher = getFetcher({
|
|
56
|
+
baseUrl,
|
|
48
57
|
responseType: 'json',
|
|
49
|
-
retry: 0,
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
retry: { count: 0 },
|
|
59
|
+
logRequest: true,
|
|
60
|
+
logResponse: true,
|
|
61
|
+
logWithBaseUrl: false, // for stable error snapshots
|
|
62
|
+
fetchFn: nativeFetchFn, // this is to make it NOT mockable
|
|
52
63
|
...opt,
|
|
64
|
+
}).onAfterResponse(async () => {
|
|
65
|
+
// This "empty" hook exists to act like `await pDelay`,
|
|
66
|
+
// so tests using it can reply on `void someAnalyticsService.doSmth()` promises
|
|
67
|
+
// to be done by that time.
|
|
68
|
+
// Smart, huh?
|
|
69
|
+
await pDelay()
|
|
53
70
|
}) as ExpressApp
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
fetcher.close = async () => {
|
|
73
|
+
const started = Date.now()
|
|
56
74
|
await new Promise(resolve => server.close(resolve))
|
|
75
|
+
console.log(`close took ${_since(started)}`) // todo: investigate why it takes ~5 seconds!
|
|
57
76
|
// server.destroy()
|
|
58
77
|
// await pDelay(1000)
|
|
59
78
|
}
|
|
60
79
|
|
|
61
|
-
return
|
|
80
|
+
return fetcher
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
/**
|