@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.
Files changed (121) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.js +14 -0
  3. package/.github/workflows/codeql-analysis.yml +74 -0
  4. package/.github/workflows/nodejs.yml +23 -0
  5. package/.github/workflows/npmpublish.yml +35 -0
  6. package/.husky/pre-commit +6 -0
  7. package/.prettierrc.js +14 -0
  8. package/@types/config.d.ts +56 -0
  9. package/CHANGELOG.md +5 -0
  10. package/LICENSE +21 -0
  11. package/README.md +28 -0
  12. package/SECURITY.md +12 -0
  13. package/__tests__/config.test.ts +31 -0
  14. package/__tests__/fake-serv/api/fake-serv.yaml +48 -0
  15. package/__tests__/fake-serv/config/config.json +15 -0
  16. package/__tests__/fake-serv/src/handlers/hello.ts +10 -0
  17. package/__tests__/fake-serv/src/index.ts +29 -0
  18. package/__tests__/fake-serv/src/routes/error.ts +13 -0
  19. package/__tests__/fake-serv/src/routes/index.ts +22 -0
  20. package/__tests__/fake-serv/src/routes/other/world.ts +7 -0
  21. package/__tests__/fake-serv.test.ts +74 -0
  22. package/build/bin/start-service.d.ts +2 -0
  23. package/build/bin/start-service.js +31 -0
  24. package/build/bin/start-service.js.map +1 -0
  25. package/build/bootstrap.d.ts +16 -0
  26. package/build/bootstrap.js +90 -0
  27. package/build/bootstrap.js.map +1 -0
  28. package/build/config/index.d.ts +10 -0
  29. package/build/config/index.js +98 -0
  30. package/build/config/index.js.map +1 -0
  31. package/build/config/schema.d.ts +48 -0
  32. package/build/config/schema.js +3 -0
  33. package/build/config/schema.js.map +1 -0
  34. package/build/config/shortstops.d.ts +31 -0
  35. package/build/config/shortstops.js +109 -0
  36. package/build/config/shortstops.js.map +1 -0
  37. package/build/config/types.d.ts +3 -0
  38. package/build/config/types.js +3 -0
  39. package/build/config/types.js.map +1 -0
  40. package/build/development/port-finder.d.ts +1 -0
  41. package/build/development/port-finder.js +41 -0
  42. package/build/development/port-finder.js.map +1 -0
  43. package/build/development/repl.d.ts +2 -0
  44. package/build/development/repl.js +29 -0
  45. package/build/development/repl.js.map +1 -0
  46. package/build/env.d.ts +2 -0
  47. package/build/env.js +19 -0
  48. package/build/env.js.map +1 -0
  49. package/build/error.d.ts +25 -0
  50. package/build/error.js +28 -0
  51. package/build/error.js.map +1 -0
  52. package/build/express-app/app.d.ts +6 -0
  53. package/build/express-app/app.js +327 -0
  54. package/build/express-app/app.js.map +1 -0
  55. package/build/express-app/index.d.ts +2 -0
  56. package/build/express-app/index.js +19 -0
  57. package/build/express-app/index.js.map +1 -0
  58. package/build/express-app/internal-server.d.ts +3 -0
  59. package/build/express-app/internal-server.js +34 -0
  60. package/build/express-app/internal-server.js.map +1 -0
  61. package/build/express-app/route-loader.d.ts +2 -0
  62. package/build/express-app/route-loader.js +46 -0
  63. package/build/express-app/route-loader.js.map +1 -0
  64. package/build/express-app/types.d.ts +14 -0
  65. package/build/express-app/types.js +3 -0
  66. package/build/express-app/types.js.map +1 -0
  67. package/build/index.d.ts +8 -0
  68. package/build/index.js +25 -0
  69. package/build/index.js.map +1 -0
  70. package/build/openapi.d.ts +5 -0
  71. package/build/openapi.js +78 -0
  72. package/build/openapi.js.map +1 -0
  73. package/build/service-calls/index.d.ts +16 -0
  74. package/build/service-calls/index.js +85 -0
  75. package/build/service-calls/index.js.map +1 -0
  76. package/build/telemetry/fetchInstrumentation.d.ts +50 -0
  77. package/build/telemetry/fetchInstrumentation.js +144 -0
  78. package/build/telemetry/fetchInstrumentation.js.map +1 -0
  79. package/build/telemetry/index.d.ts +6 -0
  80. package/build/telemetry/index.js +80 -0
  81. package/build/telemetry/index.js.map +1 -0
  82. package/build/telemetry/instrumentations.d.ts +29 -0
  83. package/build/telemetry/instrumentations.js +47 -0
  84. package/build/telemetry/instrumentations.js.map +1 -0
  85. package/build/telemetry/requestLogger.d.ts +6 -0
  86. package/build/telemetry/requestLogger.js +144 -0
  87. package/build/telemetry/requestLogger.js.map +1 -0
  88. package/build/tsconfig.build.tsbuildinfo +1 -0
  89. package/build/types.d.ts +77 -0
  90. package/build/types.js +3 -0
  91. package/build/types.js.map +1 -0
  92. package/config/config.json +31 -0
  93. package/config/development.json +11 -0
  94. package/config/test.json +5 -0
  95. package/jest.config.js +14 -0
  96. package/package.json +111 -0
  97. package/src/bin/start-service.ts +28 -0
  98. package/src/bootstrap.ts +112 -0
  99. package/src/config/index.ts +115 -0
  100. package/src/config/schema.ts +66 -0
  101. package/src/config/shortstops.ts +118 -0
  102. package/src/config/types.ts +5 -0
  103. package/src/development/port-finder.ts +40 -0
  104. package/src/development/repl.ts +24 -0
  105. package/src/env.ts +14 -0
  106. package/src/error.ts +44 -0
  107. package/src/express-app/app.ts +399 -0
  108. package/src/express-app/index.ts +2 -0
  109. package/src/express-app/internal-server.ts +31 -0
  110. package/src/express-app/route-loader.ts +48 -0
  111. package/src/express-app/types.ts +31 -0
  112. package/src/index.ts +8 -0
  113. package/src/openapi.ts +67 -0
  114. package/src/service-calls/index.ts +129 -0
  115. package/src/telemetry/fetchInstrumentation.ts +209 -0
  116. package/src/telemetry/index.ts +69 -0
  117. package/src/telemetry/instrumentations.ts +54 -0
  118. package/src/telemetry/requestLogger.ts +193 -0
  119. package/src/types.ts +139 -0
  120. package/tsconfig.build.json +10 -0
  121. 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":"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"}
@@ -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,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=schema.js.map
@@ -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,3 @@
1
+ export interface ConfigStore {
2
+ get<T>(name: string): T | undefined;
3
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -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,2 @@
1
+ import { ServiceExpress } from '../types';
2
+ export declare function serviceRepl(app: ServiceExpress, onExit: () => void): void;
@@ -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
@@ -0,0 +1,2 @@
1
+ export declare function getNodeEnv(): string | undefined;
2
+ export declare function isDev(): boolean;
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
@@ -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"}
@@ -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>>;