@openapi-typescript-infra/service 1.0.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/.eslintignore +7 -0
- package/.eslintrc.js +14 -0
- package/.github/workflows/codeql-analysis.yml +74 -0
- package/.github/workflows/nodejs.yml +23 -0
- package/.github/workflows/npmpublish.yml +35 -0
- package/.husky/pre-commit +6 -0
- package/.prettierrc.js +14 -0
- package/@types/config.d.ts +56 -0
- package/CHANGELOG.md +5 -0
- package/LICENSE +21 -0
- package/README.md +28 -0
- package/SECURITY.md +12 -0
- package/__tests__/config.test.ts +31 -0
- package/__tests__/fake-serv/api/fake-serv.yaml +48 -0
- package/__tests__/fake-serv/config/config.json +15 -0
- package/__tests__/fake-serv/src/handlers/hello.ts +10 -0
- package/__tests__/fake-serv/src/index.ts +29 -0
- package/__tests__/fake-serv/src/routes/error.ts +13 -0
- package/__tests__/fake-serv/src/routes/index.ts +22 -0
- package/__tests__/fake-serv/src/routes/other/world.ts +7 -0
- package/__tests__/fake-serv.test.ts +74 -0
- package/build/bin/start-service.d.ts +2 -0
- package/build/bin/start-service.js +31 -0
- package/build/bin/start-service.js.map +1 -0
- package/build/bootstrap.d.ts +16 -0
- package/build/bootstrap.js +90 -0
- package/build/bootstrap.js.map +1 -0
- package/build/config/index.d.ts +10 -0
- package/build/config/index.js +98 -0
- package/build/config/index.js.map +1 -0
- package/build/config/schema.d.ts +48 -0
- package/build/config/schema.js +3 -0
- package/build/config/schema.js.map +1 -0
- package/build/config/shortstops.d.ts +31 -0
- package/build/config/shortstops.js +109 -0
- package/build/config/shortstops.js.map +1 -0
- package/build/config/types.d.ts +3 -0
- package/build/config/types.js +3 -0
- package/build/config/types.js.map +1 -0
- package/build/development/port-finder.d.ts +1 -0
- package/build/development/port-finder.js +41 -0
- package/build/development/port-finder.js.map +1 -0
- package/build/development/repl.d.ts +2 -0
- package/build/development/repl.js +29 -0
- package/build/development/repl.js.map +1 -0
- package/build/env.d.ts +2 -0
- package/build/env.js +19 -0
- package/build/env.js.map +1 -0
- package/build/error.d.ts +25 -0
- package/build/error.js +28 -0
- package/build/error.js.map +1 -0
- package/build/express-app/app.d.ts +6 -0
- package/build/express-app/app.js +327 -0
- package/build/express-app/app.js.map +1 -0
- package/build/express-app/index.d.ts +2 -0
- package/build/express-app/index.js +19 -0
- package/build/express-app/index.js.map +1 -0
- package/build/express-app/internal-server.d.ts +3 -0
- package/build/express-app/internal-server.js +34 -0
- package/build/express-app/internal-server.js.map +1 -0
- package/build/express-app/route-loader.d.ts +2 -0
- package/build/express-app/route-loader.js +46 -0
- package/build/express-app/route-loader.js.map +1 -0
- package/build/express-app/types.d.ts +14 -0
- package/build/express-app/types.js +3 -0
- package/build/express-app/types.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +25 -0
- package/build/index.js.map +1 -0
- package/build/openapi.d.ts +5 -0
- package/build/openapi.js +78 -0
- package/build/openapi.js.map +1 -0
- package/build/service-calls/index.d.ts +16 -0
- package/build/service-calls/index.js +85 -0
- package/build/service-calls/index.js.map +1 -0
- package/build/telemetry/fetchInstrumentation.d.ts +50 -0
- package/build/telemetry/fetchInstrumentation.js +144 -0
- package/build/telemetry/fetchInstrumentation.js.map +1 -0
- package/build/telemetry/index.d.ts +6 -0
- package/build/telemetry/index.js +80 -0
- package/build/telemetry/index.js.map +1 -0
- package/build/telemetry/instrumentations.d.ts +29 -0
- package/build/telemetry/instrumentations.js +47 -0
- package/build/telemetry/instrumentations.js.map +1 -0
- package/build/telemetry/requestLogger.d.ts +6 -0
- package/build/telemetry/requestLogger.js +144 -0
- package/build/telemetry/requestLogger.js.map +1 -0
- package/build/tsconfig.build.tsbuildinfo +1 -0
- package/build/types.d.ts +77 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/config/config.json +31 -0
- package/config/development.json +11 -0
- package/config/test.json +5 -0
- package/jest.config.js +14 -0
- package/package.json +111 -0
- package/src/bin/start-service.ts +28 -0
- package/src/bootstrap.ts +112 -0
- package/src/config/index.ts +115 -0
- package/src/config/schema.ts +66 -0
- package/src/config/shortstops.ts +118 -0
- package/src/config/types.ts +5 -0
- package/src/development/port-finder.ts +40 -0
- package/src/development/repl.ts +24 -0
- package/src/env.ts +14 -0
- package/src/error.ts +44 -0
- package/src/express-app/app.ts +399 -0
- package/src/express-app/index.ts +2 -0
- package/src/express-app/internal-server.ts +31 -0
- package/src/express-app/route-loader.ts +48 -0
- package/src/express-app/types.ts +31 -0
- package/src/index.ts +8 -0
- package/src/openapi.ts +67 -0
- package/src/service-calls/index.ts +129 -0
- package/src/telemetry/fetchInstrumentation.ts +209 -0
- package/src/telemetry/index.ts +69 -0
- package/src/telemetry/instrumentations.ts +54 -0
- package/src/telemetry/requestLogger.ts +193 -0
- package/src/types.ts +139 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.json +36 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.bootstrap = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
|
+
const read_pkg_up_1 = __importDefault(require("read-pkg-up"));
|
|
10
|
+
const env_1 = require("./env");
|
|
11
|
+
const index_1 = require("./telemetry/index");
|
|
12
|
+
function resolveMain(packageJson) {
|
|
13
|
+
if (typeof packageJson.main === 'string') {
|
|
14
|
+
return packageJson.main;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
async function getServiceDetails(argv = {}) {
|
|
19
|
+
if (argv.name && argv.root) {
|
|
20
|
+
return {
|
|
21
|
+
rootDirectory: argv.root,
|
|
22
|
+
name: argv.name,
|
|
23
|
+
main: argv.main || ((0, env_1.isDev)() && !argv.built ? 'src/index.ts' : 'build/index.js'),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const cwd = argv.packageDir ? path_1.default.resolve(argv.packageDir) : process.cwd();
|
|
27
|
+
const pkg = await (0, read_pkg_up_1.default)({ cwd });
|
|
28
|
+
if (!pkg) {
|
|
29
|
+
throw new Error(`Unable to find package.json in ${cwd} to get main module. Make sure you are running from the package root directory.`);
|
|
30
|
+
}
|
|
31
|
+
const main = resolveMain(pkg.packageJson);
|
|
32
|
+
const parts = pkg.packageJson.name.split('/');
|
|
33
|
+
return {
|
|
34
|
+
main,
|
|
35
|
+
rootDirectory: path_1.default.dirname(pkg.path),
|
|
36
|
+
name: parts[parts.length - 1],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Automagically start your app by using common patterns
|
|
40
|
+
// to find your implementation and settings. This is most useful
|
|
41
|
+
// for jobs or other scripts that need service infra but are
|
|
42
|
+
// not simply the service
|
|
43
|
+
async function bootstrap(argv) {
|
|
44
|
+
const { main, rootDirectory, name } = await getServiceDetails(argv);
|
|
45
|
+
let entrypoint;
|
|
46
|
+
let codepath = 'build';
|
|
47
|
+
if ((0, env_1.isDev)() && argv?.built !== true) {
|
|
48
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
49
|
+
const { register } = await import('ts-node');
|
|
50
|
+
register();
|
|
51
|
+
if (main) {
|
|
52
|
+
entrypoint = main.replace(/^(\.?\/?)build\//, '$1src/').replace(/\.js$/, '.ts');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
entrypoint = './src/index.ts';
|
|
56
|
+
}
|
|
57
|
+
codepath = 'src';
|
|
58
|
+
}
|
|
59
|
+
else if (main) {
|
|
60
|
+
entrypoint = main;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
entrypoint = './build/index.js';
|
|
64
|
+
}
|
|
65
|
+
dotenv_1.default.config();
|
|
66
|
+
const absoluteEntrypoint = path_1.default.resolve(rootDirectory, entrypoint);
|
|
67
|
+
if (argv?.telemetry) {
|
|
68
|
+
return (0, index_1.startWithTelemetry)({
|
|
69
|
+
name,
|
|
70
|
+
rootDirectory,
|
|
71
|
+
service: absoluteEntrypoint,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// This needs to be required for TS on-the-fly to work
|
|
75
|
+
// eslint-disable-next-line global-require, import/no-dynamic-require, @typescript-eslint/no-var-requires
|
|
76
|
+
const impl = require(absoluteEntrypoint);
|
|
77
|
+
const opts = {
|
|
78
|
+
name,
|
|
79
|
+
rootDirectory,
|
|
80
|
+
service: impl.default || impl.service,
|
|
81
|
+
codepath,
|
|
82
|
+
};
|
|
83
|
+
// eslint-disable-next-line import/no-unresolved
|
|
84
|
+
const { startApp, listen } = await import('./express-app/app.js');
|
|
85
|
+
const app = await startApp(opts);
|
|
86
|
+
const server = argv?.nobind ? undefined : await listen(app);
|
|
87
|
+
return { server, app };
|
|
88
|
+
}
|
|
89
|
+
exports.bootstrap = bootstrap;
|
|
90
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ConfigStore } from './types';
|
|
2
|
+
export interface ServiceConfigurationSpec {
|
|
3
|
+
rootDirectory: string;
|
|
4
|
+
configurationDirectories: string[];
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadConfiguration({ name, configurationDirectories: dirs, rootDirectory, }: ServiceConfigurationSpec): Promise<ConfigStore>;
|
|
8
|
+
export declare function insertConfigurationBefore(configDirs: string[] | undefined, insert: string, before: string): string[];
|
|
9
|
+
export * from './schema';
|
|
10
|
+
export * from './types';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.insertConfigurationBefore = exports.loadConfiguration = void 0;
|
|
21
|
+
const fs_1 = __importDefault(require("fs"));
|
|
22
|
+
const path_1 = __importDefault(require("path"));
|
|
23
|
+
const confit_1 = __importDefault(require("@gasbuddy/confit"));
|
|
24
|
+
const shortstops_1 = require("./shortstops");
|
|
25
|
+
// Order matters here.
|
|
26
|
+
const ENVIRONMENTS = ['production', 'staging', 'test', 'development'];
|
|
27
|
+
async function pathExists(f) {
|
|
28
|
+
return new Promise((accept, reject) => {
|
|
29
|
+
fs_1.default.stat(f, (err) => {
|
|
30
|
+
if (!err) {
|
|
31
|
+
accept(true);
|
|
32
|
+
}
|
|
33
|
+
else if (err.code === 'ENOENT') {
|
|
34
|
+
accept(false);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
reject(err);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async function addDefaultConfiguration(configFactory, directory, envConfit) {
|
|
43
|
+
const addIfEnv = async (e) => {
|
|
44
|
+
const c = path_1.default.join(directory, `${e}.json`);
|
|
45
|
+
if (envConfit.get(`env:${e}`) && (await pathExists(c))) {
|
|
46
|
+
configFactory.addDefault(c);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
};
|
|
51
|
+
await ENVIRONMENTS.reduce((runningPromise, environment) => runningPromise.then((prev) => prev || addIfEnv(environment)), Promise.resolve(false));
|
|
52
|
+
const baseConfig = path_1.default.join(directory, 'config.json');
|
|
53
|
+
if (await pathExists(baseConfig)) {
|
|
54
|
+
configFactory.addDefault(baseConfig);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function loadConfiguration({ name, configurationDirectories: dirs, rootDirectory, }) {
|
|
58
|
+
const defaultProtocols = (0, shortstops_1.shortstops)({ name }, rootDirectory);
|
|
59
|
+
const specificConfig = dirs[dirs.length - 1];
|
|
60
|
+
// This confit version just gets us environment info
|
|
61
|
+
const envConfit = await new Promise((accept, reject) => {
|
|
62
|
+
(0, confit_1.default)(specificConfig).create((err, config) => (err ? reject(err) : accept(config)));
|
|
63
|
+
});
|
|
64
|
+
const configFactory = (0, confit_1.default)({
|
|
65
|
+
basedir: specificConfig,
|
|
66
|
+
protocols: defaultProtocols,
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Note that in confit, when using addDefault,
|
|
70
|
+
* the FIRST addDefault takes precendence over the next (and so on), so
|
|
71
|
+
* if you override this method, you should register your defaults first.
|
|
72
|
+
*/
|
|
73
|
+
const defaultOrder = dirs.slice(0, dirs.length - 1).reverse();
|
|
74
|
+
defaultOrder.push(path_1.default.join(__dirname, '../..', 'config'));
|
|
75
|
+
await defaultOrder.reduce((promise, dir) => promise.then(() => addDefaultConfiguration(configFactory, dir, envConfit)), Promise.resolve());
|
|
76
|
+
const loaded = await new Promise((accept, reject) => {
|
|
77
|
+
configFactory.create((err, config) => (err ? reject(err) : accept(config)));
|
|
78
|
+
});
|
|
79
|
+
// TODO init other stuff based on config here, such as key management or
|
|
80
|
+
// other cloud-aware shortstop handlers
|
|
81
|
+
return loaded;
|
|
82
|
+
}
|
|
83
|
+
exports.loadConfiguration = loadConfiguration;
|
|
84
|
+
function insertConfigurationBefore(configDirs, insert, before) {
|
|
85
|
+
const copy = [...(configDirs || [])];
|
|
86
|
+
const index = copy.indexOf(before);
|
|
87
|
+
if (index === -1) {
|
|
88
|
+
copy.push(insert, before);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
copy.splice(index, 0, insert);
|
|
92
|
+
}
|
|
93
|
+
return copy;
|
|
94
|
+
}
|
|
95
|
+
exports.insertConfigurationBefore = insertConfigurationBefore;
|
|
96
|
+
__exportStar(require("./schema"), exports);
|
|
97
|
+
__exportStar(require("./types"), exports);
|
|
98
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAExB,8DAAsC;AAEtC,6CAA0C;AAG1C,sBAAsB;AACtB,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAEtE,KAAK,UAAU,UAAU,CAAC,CAAS;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QACpC,YAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;YACjB,IAAI,CAAC,GAAG,EAAE;gBACR,MAAM,CAAC,IAAI,CAAC,CAAC;aACd;iBAAM,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE;gBAChC,MAAM,CAAC,KAAK,CAAC,CAAC;aACf;iBAAM;gBACL,MAAM,CAAC,GAAG,CAAC,CAAC;aACb;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,uBAAuB,CACpC,aAAwC,EACxC,SAAiB,EACjB,SAAsB;IAEtB,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAS,EAAE,EAAE;QACnC,MAAM,CAAC,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;YACtD,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC5B,OAAO,IAAI,CAAC;SACb;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,YAAY,CAAC,MAAM,CACvB,CAAC,cAAc,EAAE,WAAW,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC,EAC7F,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CACvB,CAAC;IAEF,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACvD,IAAI,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE;QAChC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;KACtC;AACH,CAAC;AAWM,KAAK,UAAU,iBAAiB,CAAC,EACtC,IAAI,EACJ,wBAAwB,EAAE,IAAI,EAC9B,aAAa,GACY;IACzB,MAAM,gBAAgB,GAAG,IAAA,uBAAU,EAAC,EAAE,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE7C,oDAAoD;IACpD,MAAM,SAAS,GAAgB,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QAClE,IAAA,gBAAM,EAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAA,gBAAM,EAAC;QAC3B,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,gBAAgB;KAC5B,CAAC,CAAC;IAEH;;;;OAIG;IACH,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IAC9D,YAAY,CAAC,IAAI,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3D,MAAM,YAAY,CAAC,MAAM,CACvB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,EAC5F,OAAO,CAAC,OAAO,EAAE,CAClB,CAAC;IAEF,MAAM,MAAM,GAAgB,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QAC/D,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,wEAAwE;IACxE,uCAAuC;IAEvC,OAAO,MAAM,CAAC;AAChB,CAAC;AArCD,8CAqCC;AAED,SAAgB,yBAAyB,CACvC,UAAgC,EAChC,MAAc,EACd,MAAc;IAEd,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC3B;SAAM;QACL,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;KAC/B;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAbD,8DAaC;AAED,2CAAyB;AACzB,0CAAwB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Level } from 'pino';
|
|
2
|
+
export interface ServiceConfiguration {
|
|
3
|
+
protocol?: string;
|
|
4
|
+
port?: number;
|
|
5
|
+
host?: string;
|
|
6
|
+
basePath?: string;
|
|
7
|
+
proxy?: string | false;
|
|
8
|
+
}
|
|
9
|
+
export interface ConfigurationItemEnabled {
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ConfigurationSchema extends Record<string, unknown> {
|
|
13
|
+
trustProxy?: string[];
|
|
14
|
+
logging?: {
|
|
15
|
+
level?: Level;
|
|
16
|
+
logHttpRequests?: boolean;
|
|
17
|
+
logRequestBody?: boolean;
|
|
18
|
+
logResponseBody?: boolean;
|
|
19
|
+
};
|
|
20
|
+
routing?: {
|
|
21
|
+
openapi?: boolean;
|
|
22
|
+
routes?: string;
|
|
23
|
+
freezeQuery?: boolean;
|
|
24
|
+
etag?: boolean;
|
|
25
|
+
cookieParser?: boolean;
|
|
26
|
+
bodyParsers?: {
|
|
27
|
+
json?: boolean;
|
|
28
|
+
form?: boolean;
|
|
29
|
+
};
|
|
30
|
+
static?: ConfigurationItemEnabled & {
|
|
31
|
+
path?: string;
|
|
32
|
+
mountPath?: string;
|
|
33
|
+
};
|
|
34
|
+
finalHandlers: {
|
|
35
|
+
notFound?: boolean;
|
|
36
|
+
errors?: ConfigurationItemEnabled & {
|
|
37
|
+
render?: boolean;
|
|
38
|
+
unnest: boolean;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
server?: {
|
|
43
|
+
internalPort?: number;
|
|
44
|
+
port?: number;
|
|
45
|
+
metrics: ConfigurationItemEnabled;
|
|
46
|
+
};
|
|
47
|
+
connections: Record<string, ServiceConfiguration>;
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import { ProtocolFn } from '@gasbuddy/confit';
|
|
5
|
+
declare const osMethods: {
|
|
6
|
+
hostname: typeof os.hostname;
|
|
7
|
+
platform: typeof os.platform;
|
|
8
|
+
type: typeof os.type;
|
|
9
|
+
version: typeof os.version;
|
|
10
|
+
};
|
|
11
|
+
export declare function shortstops(service: {
|
|
12
|
+
name: string;
|
|
13
|
+
}, sourcedir: string): {
|
|
14
|
+
env: (envVarName: string) => string | undefined;
|
|
15
|
+
env_switch(v: string): boolean;
|
|
16
|
+
base64: (blob: string) => Buffer;
|
|
17
|
+
regex(v: string): RegExp;
|
|
18
|
+
path: (relativePath: string) => string;
|
|
19
|
+
sourcepath: (relativePath: string) => string;
|
|
20
|
+
file: (relativePath: string) => string | Buffer;
|
|
21
|
+
sourcefile: (relativePath: string) => string | Buffer;
|
|
22
|
+
require: (v: string) => any;
|
|
23
|
+
sourcerequire: (v: string) => any;
|
|
24
|
+
yaml: ProtocolFn<any>;
|
|
25
|
+
servicetype: (v: string) => boolean;
|
|
26
|
+
servicename: (v: string) => string;
|
|
27
|
+
os(p: keyof typeof osMethods): string;
|
|
28
|
+
dns: ProtocolFn<string>;
|
|
29
|
+
literal(v: string): string;
|
|
30
|
+
};
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.shortstops = void 0;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const shortstop_handlers_1 = __importDefault(require("shortstop-handlers"));
|
|
10
|
+
const shortstop_yaml_1 = __importDefault(require("shortstop-yaml"));
|
|
11
|
+
const shortstop_dns_1 = __importDefault(require("shortstop-dns"));
|
|
12
|
+
/**
|
|
13
|
+
* Default shortstop handlers for GasBuddy service configuration
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* A require: shortstop that will dig and find a named function
|
|
17
|
+
* with a url-like hash pattern
|
|
18
|
+
*/
|
|
19
|
+
function betterRequire(basepath) {
|
|
20
|
+
const baseRequire = shortstop_handlers_1.default.require(basepath);
|
|
21
|
+
return function hashRequire(v) {
|
|
22
|
+
const [moduleName, func] = v.split('#');
|
|
23
|
+
const module = baseRequire(moduleName);
|
|
24
|
+
if (func) {
|
|
25
|
+
if (module[func]) {
|
|
26
|
+
return module[func];
|
|
27
|
+
}
|
|
28
|
+
return baseRequire(v);
|
|
29
|
+
}
|
|
30
|
+
return module;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Our convention is that service names end with:
|
|
35
|
+
* -serv - a back end service not callable by the outside world and where no authorization occurs
|
|
36
|
+
* -api - a non-UI front end service that exposes swagger and sometimes non-swagger APIs
|
|
37
|
+
* -web - a UI front end service
|
|
38
|
+
* -worker - a scheduled job or queue processor
|
|
39
|
+
*
|
|
40
|
+
* This shortstop will take a CSV of service types and tell you if this service is
|
|
41
|
+
* of that type, or if the first character after serviceType: is an exclamation point,
|
|
42
|
+
* whether it's NOT of any of the specified types
|
|
43
|
+
*/
|
|
44
|
+
function serviceTypeFactory(name) {
|
|
45
|
+
const type = name.split('-').pop();
|
|
46
|
+
return function serviceType(v) {
|
|
47
|
+
let checkValue = v;
|
|
48
|
+
let matchIsGood = true;
|
|
49
|
+
if (checkValue[0] === '!') {
|
|
50
|
+
matchIsGood = false;
|
|
51
|
+
checkValue = checkValue.substring(1);
|
|
52
|
+
}
|
|
53
|
+
const values = checkValue.split(',');
|
|
54
|
+
// Welp, there's no XOR so here we are.
|
|
55
|
+
return type && values.includes(type) ? matchIsGood : !matchIsGood;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const osMethods = {
|
|
59
|
+
hostname: os_1.default.hostname,
|
|
60
|
+
platform: os_1.default.platform,
|
|
61
|
+
type: os_1.default.type,
|
|
62
|
+
version: os_1.default.version,
|
|
63
|
+
};
|
|
64
|
+
function shortstops(service, sourcedir) {
|
|
65
|
+
/**
|
|
66
|
+
* Since we use transpiled sources a lot,
|
|
67
|
+
* basedir and sourcedir are meaningfully different reference points.
|
|
68
|
+
*/
|
|
69
|
+
const basedir = path_1.default.join(sourcedir, '..');
|
|
70
|
+
const env = shortstop_handlers_1.default.env();
|
|
71
|
+
return {
|
|
72
|
+
env,
|
|
73
|
+
// A version of env that can default to false
|
|
74
|
+
env_switch(v) {
|
|
75
|
+
if (v && v[0] === '!') {
|
|
76
|
+
const bval = env(`${v.substring(1)}|b`);
|
|
77
|
+
return !bval;
|
|
78
|
+
}
|
|
79
|
+
return !!env(v);
|
|
80
|
+
},
|
|
81
|
+
base64: shortstop_handlers_1.default.base64(),
|
|
82
|
+
regex(v) {
|
|
83
|
+
const [, pattern, flags] = v.match(/^\/(.*)\/([a-z]*)/) || [];
|
|
84
|
+
return new RegExp(pattern, flags);
|
|
85
|
+
},
|
|
86
|
+
// handle source and base directory intelligently
|
|
87
|
+
path: shortstop_handlers_1.default.path(basedir),
|
|
88
|
+
sourcepath: shortstop_handlers_1.default.path(sourcedir),
|
|
89
|
+
file: shortstop_handlers_1.default.file(basedir),
|
|
90
|
+
sourcefile: shortstop_handlers_1.default.file(sourcedir),
|
|
91
|
+
require: betterRequire(basedir),
|
|
92
|
+
sourcerequire: betterRequire(sourcedir),
|
|
93
|
+
// Sometimes yaml is more pleasant for configuration
|
|
94
|
+
yaml: (0, shortstop_yaml_1.default)(basedir),
|
|
95
|
+
// Switch on service type
|
|
96
|
+
servicetype: serviceTypeFactory(service.name),
|
|
97
|
+
servicename: (v) => v.replace(/\$\{name\}/g, service.name),
|
|
98
|
+
os(p) {
|
|
99
|
+
return osMethods[p]();
|
|
100
|
+
},
|
|
101
|
+
dns: (0, shortstop_dns_1.default)(),
|
|
102
|
+
// No-op in case you have values that start with a shortstop handler name (and colon)
|
|
103
|
+
literal(v) {
|
|
104
|
+
return v;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
exports.shortstops = shortstops;
|
|
109
|
+
//# sourceMappingURL=shortstops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortstops.js","sourceRoot":"","sources":["../../src/config/shortstops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findPort(start: number): Promise<number | null>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findPort = void 0;
|
|
7
|
+
const net_1 = __importDefault(require("net"));
|
|
8
|
+
// Inspired by https://github.com/kessler/find-port/blob/master/lib/findPort.js
|
|
9
|
+
async function isAvailable(port) {
|
|
10
|
+
return new Promise((accept, reject) => {
|
|
11
|
+
const server = net_1.default.createServer().listen(port);
|
|
12
|
+
const timeoutRef = setTimeout(() => {
|
|
13
|
+
accept(false);
|
|
14
|
+
}, 2000);
|
|
15
|
+
timeoutRef.unref();
|
|
16
|
+
server.once('listening', () => {
|
|
17
|
+
clearTimeout(timeoutRef);
|
|
18
|
+
server.close();
|
|
19
|
+
accept(true);
|
|
20
|
+
});
|
|
21
|
+
server.once('error', (err) => {
|
|
22
|
+
clearTimeout(timeoutRef);
|
|
23
|
+
if (err.code === 'EADDRINUSE') {
|
|
24
|
+
accept(false);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
reject(err);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function findPort(start) {
|
|
32
|
+
for (let p = start; p < start + 1000; p += 1) {
|
|
33
|
+
// eslint-disable-next-line no-await-in-loop
|
|
34
|
+
if (await isAvailable(p)) {
|
|
35
|
+
return p;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
exports.findPort = findPort;
|
|
41
|
+
//# sourceMappingURL=port-finder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-finder.js","sourceRoot":"","sources":["../../src/development/port-finder.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAsB;AAEtB,+EAA+E;AAC/E,KAAK,UAAU,WAAW,CAAC,IAAY;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,aAAG,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE/C,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,EAAE,IAAI,CAAC,CAAC;QAET,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,YAAY,CAAC,UAAU,CAAC,CAAC;YACzB,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,YAAY,CAAC,UAAU,CAAC,CAAC;YAEzB,IAAK,GAA0B,CAAC,IAAI,KAAK,YAAY,EAAE;gBACrD,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;aACR;YAED,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,KAAa;IAC1C,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE;QAC5C,4CAA4C;QAC5C,IAAI,MAAM,WAAW,CAAC,CAAC,CAAC,EAAE;YACxB,OAAO,CAAC,CAAC;SACV;KACF;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AARD,4BAQC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.serviceRepl = void 0;
|
|
7
|
+
const repl_1 = __importDefault(require("repl"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function serviceRepl(app, onExit) {
|
|
10
|
+
const rl = repl_1.default.start({
|
|
11
|
+
prompt: '> ',
|
|
12
|
+
});
|
|
13
|
+
Object.assign(rl.context, app.locals, {
|
|
14
|
+
app,
|
|
15
|
+
dump(o) {
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
console.log(JSON.stringify(o, null, '\t'));
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
rl.setupHistory(path_1.default.resolve('.node_repl_history'), (err) => {
|
|
21
|
+
if (err) {
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
console.error('History setup failed', err);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
rl.on('exit', onExit);
|
|
27
|
+
}
|
|
28
|
+
exports.serviceRepl = serviceRepl;
|
|
29
|
+
//# sourceMappingURL=repl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repl.js","sourceRoot":"","sources":["../../src/development/repl.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,gDAAwB;AAIxB,SAAgB,WAAW,CAAC,GAAmB,EAAE,MAAkB;IACjE,MAAM,EAAE,GAAG,cAAI,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QACpC,GAAG;QACH,IAAI,CAAC,CAAU;YACb,sCAAsC;YACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC,CAAC;IACH,EAAE,CAAC,YAAY,CAAC,cAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1D,IAAI,GAAG,EAAE;YACP,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;SAC5C;IACH,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxB,CAAC;AAlBD,kCAkBC"}
|
package/build/env.d.ts
ADDED
package/build/env.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDev = exports.getNodeEnv = void 0;
|
|
4
|
+
function getNodeEnv() {
|
|
5
|
+
switch (process.env.APP_ENV || process.env.NODE_ENV) {
|
|
6
|
+
case 'production':
|
|
7
|
+
case 'staging':
|
|
8
|
+
case 'test':
|
|
9
|
+
return process.env.APP_ENV || process.env.NODE_ENV;
|
|
10
|
+
default:
|
|
11
|
+
return 'development';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.getNodeEnv = getNodeEnv;
|
|
15
|
+
function isDev() {
|
|
16
|
+
return getNodeEnv() === 'development';
|
|
17
|
+
}
|
|
18
|
+
exports.isDev = isDev;
|
|
19
|
+
//# sourceMappingURL=env.js.map
|
package/build/env.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":";;;AAAA,SAAgB,UAAU;IACxB,QAAQ,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;QACnD,KAAK,YAAY,CAAC;QAClB,KAAK,SAAS,CAAC;QACf,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QACrD;YACE,OAAO,aAAa,CAAC;KACxB;AACH,CAAC;AATD,gCASC;AAED,SAAgB,KAAK;IACnB,OAAO,UAAU,EAAE,KAAK,aAAa,CAAC;AACxC,CAAC;AAFD,sBAEC"}
|
package/build/error.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ServiceLike, ServiceLocals } from './types';
|
|
2
|
+
export interface ServiceErrorSpec {
|
|
3
|
+
status?: number;
|
|
4
|
+
code?: string;
|
|
5
|
+
domain?: string;
|
|
6
|
+
display_message?: string;
|
|
7
|
+
log_stack?: boolean;
|
|
8
|
+
expected_error?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* An error that gives more structured information to callers. Throw inside a handler as
|
|
12
|
+
*
|
|
13
|
+
* throw new Error(req, 'Something broke', { code: 'SomethingBroke', status: 400 });
|
|
14
|
+
*
|
|
15
|
+
* You can also include a display_message which is intended to be viewed by the end user
|
|
16
|
+
*/
|
|
17
|
+
export declare class ServiceError extends Error {
|
|
18
|
+
status: number | undefined;
|
|
19
|
+
code?: string;
|
|
20
|
+
domain: string;
|
|
21
|
+
display_message?: string;
|
|
22
|
+
log_stack?: boolean;
|
|
23
|
+
expected_error?: boolean;
|
|
24
|
+
constructor(app: ServiceLike<ServiceLocals>, message: string, spec?: ServiceErrorSpec);
|
|
25
|
+
}
|
package/build/error.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServiceError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* An error that gives more structured information to callers. Throw inside a handler as
|
|
6
|
+
*
|
|
7
|
+
* throw new Error(req, 'Something broke', { code: 'SomethingBroke', status: 400 });
|
|
8
|
+
*
|
|
9
|
+
* You can also include a display_message which is intended to be viewed by the end user
|
|
10
|
+
*/
|
|
11
|
+
class ServiceError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
code;
|
|
14
|
+
domain;
|
|
15
|
+
display_message;
|
|
16
|
+
log_stack;
|
|
17
|
+
// If true, this shouldn't be logged as an error, but as an info log.
|
|
18
|
+
// This is common when the error needs to go to the client, but should not
|
|
19
|
+
// take up the valuable mental space of an error log.
|
|
20
|
+
expected_error;
|
|
21
|
+
constructor(app, message, spec) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.domain = app.locals.name;
|
|
24
|
+
Object.assign(this, spec);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.ServiceError = ServiceError;
|
|
28
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":";;;AAWA;;;;;;GAMG;AACH,MAAa,YAAa,SAAQ,KAAK;IAC9B,MAAM,CAAqB;IAE3B,IAAI,CAAU;IAEd,MAAM,CAAS;IAEf,eAAe,CAAU;IAEzB,SAAS,CAAW;IAE3B,qEAAqE;IACrE,0EAA0E;IAC1E,qDAAqD;IAC9C,cAAc,CAAW;IAEhC,YACE,GAA+B,EAC/B,OAAe,EACf,IAAuB;QAEvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAzBD,oCAyBC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import http from 'http';
|
|
3
|
+
import type { RequestLocals, ServiceExpress, ServiceLocals, ServiceStartOptions } from '../types';
|
|
4
|
+
export declare function startApp<SLocals extends ServiceLocals = ServiceLocals, RLocals extends RequestLocals = RequestLocals>(startOptions: ServiceStartOptions<SLocals, RLocals>): Promise<ServiceExpress<SLocals>>;
|
|
5
|
+
export declare function shutdownApp(app: ServiceExpress): Promise<void>;
|
|
6
|
+
export declare function listen<SLocals extends ServiceLocals = ServiceLocals>(app: ServiceExpress<SLocals>, shutdownHandler?: () => Promise<void>): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|