@naturalcycles/backend-lib 4.18.7 → 4.19.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 CHANGED
@@ -8,13 +8,27 @@
8
8
  // Target/module
9
9
  "target": "es2022",
10
10
  "lib": ["esnext"], // add "dom" if needed
11
- "module": "commonjs",
12
- "moduleResolution": "node",
11
+ // module `nodenext` is a modern mode that auto-detects cjs/esm
12
+ // it also defaults `esModuleInterop` and `allowSyntheticDefaultImports` to true
13
+ "module": "nodenext",
14
+ "moduleResolution": "nodenext",
13
15
  "moduleDetection": "force",
16
+ // specifying these explicitly for better IDE compatibility (but they're on by default with module=nodenext)
17
+ "esModuleInterop": true,
18
+ "allowSyntheticDefaultImports": true,
19
+ // Faster compilation in general
20
+ // Support for external compilers (e.g esbuild)
21
+ // Speedup in Jest by using "isolatedModules" in 'ts-jest' config
22
+ "isolatedModules": true,
14
23
 
15
24
  // Emit
16
25
  "sourceMap": false,
17
26
  "declaration": false,
27
+ // Otherwise since es2022 it defaults to true
28
+ // and starts to produce different/unexpected behavior
29
+ // https://angular.schule/blog/2022-11-use-define-for-class-fields
30
+ "useDefineForClassFields": false,
31
+ "importHelpers": true,
18
32
 
19
33
  // Strictness
20
34
  "strict": true,
@@ -25,19 +39,10 @@
25
39
  "noImplicitOverride": true,
26
40
  "noUncheckedIndexedAccess": true,
27
41
  "noPropertyAccessFromIndexSignature": true,
28
- // Otherwise since es2022 it defaults to true
29
- // and starts to produce different/unexpected behavior
30
- // https://angular.schule/blog/2022-11-use-define-for-class-fields
31
- "useDefineForClassFields": false,
32
42
 
33
43
  // Enabled should be faster, but will catch less errors
34
44
  // "skipLibCheck": true,
35
45
 
36
- // Faster compilation in general
37
- // Support for external compilers (e.g esbuild)
38
- // Speedup in Jest by using "isolatedModules" in 'ts-jest' config
39
- "isolatedModules": true,
40
-
41
46
  // Disabled because of https://github.com/Microsoft/TypeScript/issues/29172
42
47
  // Need to be specified in the project tsconfig
43
48
  // "outDir": "dist",
@@ -54,7 +59,6 @@
54
59
  // Other
55
60
  "pretty": true,
56
61
  "newLine": "lf",
57
- "importHelpers": true,
58
62
  "experimentalDecorators": true
59
63
  }
60
64
  // Need to be specified in the project tsconfig
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getLoginHtmlRedirect = exports.loginHtml = exports.requireAdminPermissions = exports.createAdminMiddleware = void 0;
4
- const fs = require("node:fs");
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
6
  const js_lib_1 = require("@naturalcycles/js-lib");
6
- const ejs = require("ejs");
7
+ const ejs_1 = tslib_1.__importDefault(require("ejs"));
7
8
  function createAdminMiddleware(adminService, cfgDefaults = {}) {
8
9
  return (reqPermissions, cfg) => requireAdminPermissions(adminService, reqPermissions, {
9
10
  ...cfgDefaults,
@@ -52,8 +53,8 @@ function loginHtml(firebaseServiceCfg) {
52
53
  exports.loginHtml = loginHtml;
53
54
  const getLoginHtml = (0, js_lib_1._memoFn)((cfg) => {
54
55
  console.log(`reading login.html`);
55
- const tmpl = fs.readFileSync(`${__dirname}/login.html`, 'utf8');
56
- return ejs.render(tmpl, cfg);
56
+ const tmpl = node_fs_1.default.readFileSync(`${__dirname}/login.html`, 'utf8');
57
+ return ejs_1.default.render(tmpl, cfg);
57
58
  });
58
59
  function getLoginHtmlRedirect(href) {
59
60
  return `
@@ -1,4 +1,4 @@
1
- import type * as FirebaseAdmin from 'firebase-admin';
1
+ import type FirebaseAdmin from 'firebase-admin';
2
2
  import { BackendRequest, BackendRequestHandler } from '../server/server.model';
3
3
  export interface AdminServiceCfg {
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import type { AppOptions, ServiceAccount } from 'firebase-admin';
2
- import type * as FirebaseAdmin from 'firebase-admin';
2
+ import type FirebaseAdmin from 'firebase-admin';
3
3
  export interface FirebaseSharedServiceCfg {
4
4
  /**
5
5
  * If undefined - will try to use credential.applicationDefault()
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
4
5
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
5
- const yargs = require("yargs");
6
+ const yargs_1 = tslib_1.__importDefault(require("yargs"));
6
7
  const deployGae_1 = require("../deploy/deployGae");
7
8
  const deployHealthCheck_1 = require("../deploy/deployHealthCheck");
8
9
  const deployPrepare_1 = require("../deploy/deployPrepare");
9
10
  (0, nodejs_lib_1.runScript)(async () => {
10
- const opt = yargs.options({
11
+ const opt = yargs_1.default.options({
11
12
  ...deployPrepare_1.deployPrepareYargsOptions,
12
13
  ...deployHealthCheck_1.deployHealthCheckYargsOptions,
13
14
  }).argv;
@@ -9,11 +9,12 @@ 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 tslib_1 = require("tslib");
12
13
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
13
- const yargs = require("yargs");
14
+ const yargs_1 = tslib_1.__importDefault(require("yargs"));
14
15
  const deployHealthCheck_1 = require("../deploy/deployHealthCheck");
15
16
  (0, nodejs_lib_1.runScript)(async () => {
16
- const { url, ...opt } = yargs.options({
17
+ const { url, ...opt } = yargs_1.default.options({
17
18
  ...deployHealthCheck_1.deployHealthCheckYargsOptions,
18
19
  url: {
19
20
  type: 'string',
@@ -6,11 +6,12 @@ yarn deploy-prepare
6
6
 
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
+ const tslib_1 = require("tslib");
9
10
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
10
- const yargs = require("yargs");
11
+ const yargs_1 = tslib_1.__importDefault(require("yargs"));
11
12
  const deployPrepare_1 = require("../deploy/deployPrepare");
12
13
  (0, nodejs_lib_1.runScript)(async () => {
13
- const opt = yargs.options(deployPrepare_1.deployPrepareYargsOptions).argv;
14
+ const opt = yargs_1.default.options(deployPrepare_1.deployPrepareYargsOptions).argv;
14
15
  await (0, deployPrepare_1.deployPrepare)(opt);
15
16
  });
16
17
  // deploy strategy
@@ -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 { GetGotOptions, ReadableTyped } from '@naturalcycles/nodejs-lib';
4
- export interface HttpDBCfg extends GetGotOptions {
5
- prefixUrl: string;
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 got;
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.got = (0, nodejs_lib_1.getGot)(cfg);
17
+ this.fetcher = (0, js_lib_1.getFetcher)(cfg);
18
18
  }
19
19
  async ping() {
20
- await this.got(`ping`);
20
+ await this.fetcher.getVoid(`ping`);
21
21
  }
22
22
  async getTables() {
23
- return await this.got(`tables`).json();
23
+ return await this.fetcher.get(`tables`);
24
24
  }
25
25
  async getTableSchema(table) {
26
- return await this.got(`${table}/schema`).json();
26
+ return await this.fetcher.get(`${table}/schema`);
27
27
  }
28
28
  async resetCache(table = '') {
29
- await this.got.put(`resetCache/${table}`);
29
+ await this.fetcher.putVoid(`resetCache/${table}`);
30
30
  }
31
31
  async getByIds(table, ids, opt) {
32
- return await this.got
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.got
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.got
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.got.put(`saveBatch`, {
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.got
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.got
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`);
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getBackendCfg = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
5
- const yaml = require("js-yaml");
6
+ const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
6
7
  const paths_cnst_1 = require("../paths.cnst");
7
8
  const backendCfgSchema = nodejs_lib_1.AjvSchema.readJsonSync(`${paths_cnst_1.resourcesDir}/backendCfg.schema.json`, {
8
9
  objectName: 'backend.cfg.yaml',
@@ -12,7 +13,7 @@ function getBackendCfg(projectDir = '.') {
12
13
  (0, nodejs_lib_1.requireFileToExist)(backendCfgYamlPath);
13
14
  const backendCfg = {
14
15
  serviceWithBranchName: true,
15
- ...yaml.load((0, nodejs_lib_1._readFileSync)(backendCfgYamlPath)),
16
+ ...js_yaml_1.default.load((0, nodejs_lib_1._readFileSync)(backendCfgYamlPath)),
16
17
  };
17
18
  backendCfgSchema.validate(backendCfg);
18
19
  return backendCfg;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateGAEServiceName = exports.createAppYaml = exports.createAndSaveAppYaml = exports.createDeployInfo = exports.createAndSaveDeployInfo = void 0;
4
- const fs = require("node:fs");
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
6
  const js_lib_1 = require("@naturalcycles/js-lib");
6
7
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
7
- const yaml = require("js-yaml");
8
+ const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
8
9
  const APP_YAML_DEFAULT = () => ({
9
10
  runtime: 'nodejs18',
10
11
  service: 'default',
@@ -26,7 +27,7 @@ const APP_YAML_DEFAULT = () => ({
26
27
  async function createAndSaveDeployInfo(backendCfg, targetDir) {
27
28
  const deployInfo = await createDeployInfo(backendCfg);
28
29
  const deployInfoPath = `${targetDir}/deployInfo.json`;
29
- fs.writeFileSync(deployInfoPath, JSON.stringify(deployInfo, null, 2));
30
+ node_fs_1.default.writeFileSync(deployInfoPath, JSON.stringify(deployInfo, null, 2));
30
31
  console.log(`saved ${(0, nodejs_lib_1.dimGrey)(deployInfoPath)}`);
31
32
  return deployInfo;
32
33
  }
@@ -73,7 +74,7 @@ exports.createDeployInfo = createDeployInfo;
73
74
  function createAndSaveAppYaml(backendCfg, deployInfo, projectDir, targetDir, appYamlPassEnv = '') {
74
75
  const appYaml = createAppYaml(backendCfg, deployInfo, projectDir, appYamlPassEnv);
75
76
  const appYamlPath = `${targetDir}/app.yaml`;
76
- fs.writeFileSync(appYamlPath, yaml.dump(appYaml));
77
+ node_fs_1.default.writeFileSync(appYamlPath, js_yaml_1.default.dump(appYaml));
77
78
  console.log(`saved ${(0, nodejs_lib_1.dimGrey)(appYamlPath)}`);
78
79
  return appYaml;
79
80
  }
@@ -89,14 +90,14 @@ function createAppYaml(backendCfg, deployInfo, projectDir, appYamlPassEnv = '')
89
90
  const appYaml = APP_YAML_DEFAULT();
90
91
  // Check existing app.yaml
91
92
  const appYamlPath = `${projectDir}/app.yaml`;
92
- if (fs.existsSync(appYamlPath)) {
93
+ if (node_fs_1.default.existsSync(appYamlPath)) {
93
94
  console.log(`merging-in ${(0, nodejs_lib_1.dimGrey)(appYamlPath)}`);
94
- (0, js_lib_1._merge)(appYaml, yaml.load(fs.readFileSync(appYamlPath, 'utf8')));
95
+ (0, js_lib_1._merge)(appYaml, js_yaml_1.default.load(node_fs_1.default.readFileSync(appYamlPath, 'utf8')));
95
96
  }
96
97
  const appEnvYamlPath = `${projectDir}/app.${APP_ENV}.yaml`;
97
- if (fs.existsSync(appEnvYamlPath)) {
98
+ if (node_fs_1.default.existsSync(appEnvYamlPath)) {
98
99
  console.log(`merging-in ${(0, nodejs_lib_1.dimGrey)(appEnvYamlPath)}`);
99
- (0, js_lib_1._merge)(appYaml, yaml.load(fs.readFileSync(appEnvYamlPath, 'utf8')));
100
+ (0, js_lib_1._merge)(appYaml, js_yaml_1.default.load(node_fs_1.default.readFileSync(appEnvYamlPath, 'utf8')));
100
101
  }
101
102
  // appYamlPassEnv
102
103
  require('dotenv').config(); // ensure .env is read
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.testDir = exports.srcDir = exports.resourcesDir = exports.projectDir = void 0;
4
- const path = require("node:path");
5
- exports.projectDir = path.join(__dirname, '/..');
4
+ const tslib_1 = require("tslib");
5
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
+ exports.projectDir = node_path_1.default.join(__dirname, '/..');
6
7
  exports.resourcesDir = `${exports.projectDir}/resources`;
7
8
  exports.srcDir = `${exports.projectDir}/src`;
8
9
  exports.testDir = `${exports.srcDir}/test`;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDeployInfo = void 0;
4
- const fs = require("node:fs");
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
5
6
  const js_lib_1 = require("@naturalcycles/js-lib");
6
7
  exports.getDeployInfo = (0, js_lib_1._memoFn)((projectDir) => {
7
8
  const deployInfoPath = `${projectDir}/deployInfo.json`;
8
9
  try {
9
- return JSON.parse(fs.readFileSync(deployInfoPath, 'utf8'));
10
+ return JSON.parse(node_fs_1.default.readFileSync(deployInfoPath, 'utf8'));
10
11
  }
11
12
  catch {
12
13
  // console.error(`cannot read ${deployInfoPath}, returning empty version`)
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDefaultRouter = void 0;
4
- const express_promise_router_1 = require("express-promise-router");
4
+ const tslib_1 = require("tslib");
5
+ const express_promise_router_1 = tslib_1.__importDefault(require("express-promise-router"));
5
6
  /**
6
7
  * Convenience method.
7
8
  */
@@ -1,13 +1,13 @@
1
- import { GetGotOptions, Got } from '@naturalcycles/nodejs-lib';
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 Got {
4
+ export interface ExpressApp extends Fetcher {
5
5
  close: () => Promise<void>;
6
6
  }
7
7
  declare class ExpressTestService {
8
- createAppFromResource(resource: BackendRequestHandlerCfg, opt?: GetGotOptions, defaultAppCfg?: DefaultAppCfg): ExpressApp;
9
- createAppFromResources(resources: BackendRequestHandlerCfg[], opt?: GetGotOptions): ExpressApp;
10
- createApp(app: BackendApplication, opt?: GetGotOptions): ExpressApp;
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 nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
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 prefixUrl = `http://127.0.0.1:${port}`;
27
- const got = (0, nodejs_lib_1.getGot)({
28
- prefixUrl,
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
- logStart: true,
32
- logFinished: true,
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
- got.close = async () => {
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 got;
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.7",
3
+ "version": "4.19.0",
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": "^12.0.0",
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,6 +1,6 @@
1
- import * as fs from 'node:fs'
1
+ import fs from 'node:fs'
2
2
  import { _memoFn, AppError } from '@naturalcycles/js-lib'
3
- import * as ejs from 'ejs'
3
+ import ejs from 'ejs'
4
4
  import { BackendRequestHandler } from '../server/server.model'
5
5
  import { BaseAdminService } from './base.admin.service'
6
6
  import { FirebaseSharedServiceCfg } from './firebase.shared.service'
@@ -1,6 +1,6 @@
1
1
  import { _assert, AppError } from '@naturalcycles/js-lib'
2
2
  import { dimGrey, green, red } from '@naturalcycles/nodejs-lib'
3
- import type * as FirebaseAdmin from 'firebase-admin'
3
+ import type FirebaseAdmin from 'firebase-admin'
4
4
  import { BackendRequest, BackendRequestHandler } from '../server/server.model'
5
5
 
6
6
  export interface AdminServiceCfg {
@@ -1,6 +1,6 @@
1
1
  import { _Memo } from '@naturalcycles/js-lib'
2
2
  import type { AppOptions, ServiceAccount } from 'firebase-admin'
3
- import type * as FirebaseAdmin from 'firebase-admin'
3
+ import type FirebaseAdmin from 'firebase-admin'
4
4
 
5
5
  export interface FirebaseSharedServiceCfg {
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { runScript } from '@naturalcycles/nodejs-lib'
4
- import * as yargs from 'yargs'
4
+ import yargs from 'yargs'
5
5
  import { deployGae } from '../deploy/deployGae'
6
6
  import { deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck'
7
7
  import { deployPrepareYargsOptions } from '../deploy/deployPrepare'
@@ -10,7 +10,7 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
10
10
  */
11
11
 
12
12
  import { runScript } from '@naturalcycles/nodejs-lib'
13
- import * as yargs from 'yargs'
13
+ import yargs from 'yargs'
14
14
  import { deployHealthCheck, deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck'
15
15
 
16
16
  runScript(async () => {
@@ -7,7 +7,7 @@ yarn deploy-prepare
7
7
  */
8
8
 
9
9
  import { runScript } from '@naturalcycles/nodejs-lib'
10
- import * as yargs from 'yargs'
10
+ import yargs from 'yargs'
11
11
  import { deployPrepare, deployPrepareYargsOptions } from '../deploy/deployPrepare'
12
12
 
13
13
  runScript(async () => {
package/src/db/httpDB.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { Readable } from 'node:stream'
2
- import { JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib'
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 { getGot, GetGotOptions, Got, ReadableTyped } from '@naturalcycles/nodejs-lib'
18
+ import { ReadableTyped } from '@naturalcycles/nodejs-lib'
13
19
 
14
- export interface HttpDBCfg extends GetGotOptions {
15
- prefixUrl: string
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.got = getGot(cfg)
34
+ this.fetcher = getFetcher(cfg)
29
35
  }
30
36
 
31
- private got!: Got
37
+ private fetcher!: Fetcher
32
38
 
33
39
  override async ping(): Promise<void> {
34
- await this.got(`ping`)
40
+ await this.fetcher.getVoid(`ping`)
35
41
  }
36
42
 
37
43
  override async getTables(): Promise<string[]> {
38
- return await this.got(`tables`).json()
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.got(`${table}/schema`).json()
50
+ return await this.fetcher.get(`${table}/schema`)
45
51
  }
46
52
 
47
53
  async resetCache(table = ''): Promise<void> {
48
- await this.got.put(`resetCache/${table}`)
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.got
57
- .put(`getByIds`, {
58
- json: {
59
- table,
60
- ids,
61
- opt,
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.got
72
- .put(`runQuery`, {
73
- json: {
74
- query,
75
- opt,
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.got
86
- .put(`runQueryCount`, {
87
- json: {
88
- query,
89
- opt,
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.got.put(`saveBatch`, {
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.got
111
- .put(`deleteByIds`, {
112
- json: {
113
- table,
114
- ids,
115
- opt,
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.got
126
- .put(`deleteByQuery`, {
127
- json: {
128
- query,
129
- opt,
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 { StringMap } from '@naturalcycles/js-lib'
2
2
  import { _readFileSync, AjvSchema, requireFileToExist } from '@naturalcycles/nodejs-lib'
3
- import * as yaml from 'js-yaml'
3
+ import yaml from 'js-yaml'
4
4
  import { resourcesDir } from '../paths.cnst'
5
5
 
6
6
  export interface BackendCfg {
@@ -1,7 +1,7 @@
1
- import * as fs from 'node:fs'
1
+ import fs from 'node:fs'
2
2
  import { _mapValues, _merge, _truncate, localTime } from '@naturalcycles/js-lib'
3
3
  import { dimGrey, white } from '@naturalcycles/nodejs-lib'
4
- import * as yaml from 'js-yaml'
4
+ import yaml from 'js-yaml'
5
5
  import { BackendCfg } from './backend.cfg.util'
6
6
  import { AppYaml, DeployInfo } from './deploy.model'
7
7
 
package/src/paths.cnst.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as path from 'node:path'
1
+ import path from 'node:path'
2
2
 
3
3
  export const projectDir = path.join(__dirname, '/..')
4
4
  export const resourcesDir = `${projectDir}/resources`
@@ -1,4 +1,4 @@
1
- import * as fs from 'node:fs'
1
+ import fs from 'node:fs'
2
2
  import { _memoFn } from '@naturalcycles/js-lib'
3
3
  import type { DeployInfo } from '../deploy'
4
4
 
@@ -1,10 +1,19 @@
1
1
  import { Server } from 'node:http'
2
2
  import { AddressInfo } from 'node:net'
3
- import { getGot, GetGotOptions, Got } from '@naturalcycles/nodejs-lib'
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
- export interface ExpressApp extends Got {
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?: GetGotOptions,
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?: GetGotOptions): ExpressApp {
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?: GetGotOptions): ExpressApp {
50
+ createApp(app: BackendApplication, opt?: FetcherOptions): ExpressApp {
42
51
  const server = this.createTestServer(app)
43
52
  const { port } = server.address() as AddressInfo
44
- const prefixUrl = `http://127.0.0.1:${port}`
53
+ const baseUrl = `http://127.0.0.1:${port}`
45
54
 
46
- const got = getGot({
47
- prefixUrl,
55
+ const fetcher = getFetcher({
56
+ baseUrl,
48
57
  responseType: 'json',
49
- retry: 0,
50
- logStart: true,
51
- logFinished: true,
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
- got.close = async () => {
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 got
80
+ return fetcher
62
81
  }
63
82
 
64
83
  /**