@openapi-typescript-infra/service 2.0.2 → 2.1.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/.trunk/trunk.yaml +6 -6
- package/CHANGELOG.md +7 -0
- package/build/bootstrap.d.ts +2 -1
- package/build/config/schema.d.ts +3 -1
- package/build/express-app/app.d.ts +3 -1
- package/build/express-app/app.js +14 -3
- package/build/express-app/app.js.map +1 -1
- package/build/express-app/internal-server.js +6 -1
- package/build/express-app/internal-server.js.map +1 -1
- package/build/telemetry/index.d.ts +2 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/config/development.json +6 -2
- package/config/test.json +2 -1
- package/package.json +13 -11
- package/src/config/schema.ts +16 -10
- package/src/express-app/app.ts +22 -3
- package/src/express-app/internal-server.ts +7 -1
- package/tsconfig.json +1 -1
package/config/development.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "tsschema://../src/config/schema#ConfigurationSchema",
|
|
2
3
|
"logging": {
|
|
3
4
|
"level": "debug"
|
|
4
5
|
},
|
|
5
|
-
"
|
|
6
|
+
"server": {
|
|
7
|
+
"port": 0,
|
|
8
|
+
"internalPort": 0
|
|
9
|
+
},
|
|
6
10
|
"connections": {
|
|
7
11
|
"default": {
|
|
8
12
|
"proxy": "http://localhost:9990"
|
|
9
13
|
}
|
|
10
14
|
}
|
|
11
|
-
}
|
|
15
|
+
}
|
package/config/test.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openapi-typescript-infra/service",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "An opinionated framework for building configuration driven services - web, api, or ob. Uses OpenAPI, pino logging, express, confit, Typescript and vitest.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.41.2",
|
|
68
68
|
"@opentelemetry/instrumentation": "^0.41.2",
|
|
69
69
|
"@opentelemetry/instrumentation-aws-sdk": "^0.36.0",
|
|
70
|
-
"@opentelemetry/instrumentation-dns": "^0.32.
|
|
70
|
+
"@opentelemetry/instrumentation-dns": "^0.32.2",
|
|
71
71
|
"@opentelemetry/instrumentation-express": "^0.33.1",
|
|
72
72
|
"@opentelemetry/instrumentation-generic-pool": "^0.32.2",
|
|
73
73
|
"@opentelemetry/instrumentation-graphql": "^0.35.1",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"dotenv": "^16.3.1",
|
|
84
84
|
"eventsource": "^1.1.2",
|
|
85
85
|
"express": "next",
|
|
86
|
-
"express-openapi-validator": "^5.0.
|
|
86
|
+
"express-openapi-validator": "^5.0.6",
|
|
87
87
|
"glob": "^8.1.0",
|
|
88
88
|
"lodash": "^4.17.21",
|
|
89
89
|
"minimist": "^1.2.8",
|
|
@@ -97,31 +97,33 @@
|
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@commitlint/cli": "^17.7.1",
|
|
99
99
|
"@commitlint/config-conventional": "^17.7.0",
|
|
100
|
-
"@openapi-typescript-infra/coconfig": "^4.
|
|
100
|
+
"@openapi-typescript-infra/coconfig": "^4.1.0",
|
|
101
101
|
"@semantic-release/changelog": "^6.0.3",
|
|
102
|
-
"@semantic-release/commit-analyzer": "^10.0.
|
|
102
|
+
"@semantic-release/commit-analyzer": "^10.0.4",
|
|
103
103
|
"@semantic-release/exec": "^6.0.3",
|
|
104
104
|
"@semantic-release/git": "^10.0.1",
|
|
105
|
-
"@semantic-release/release-notes-generator": "^11.0.
|
|
105
|
+
"@semantic-release/release-notes-generator": "^11.0.7",
|
|
106
106
|
"@types/cookie-parser": "^1.4.3",
|
|
107
107
|
"@types/eventsource": "1.1.11",
|
|
108
108
|
"@types/express": "^4.17.17",
|
|
109
109
|
"@types/glob": "^8.1.0",
|
|
110
110
|
"@types/lodash": "^4.14.197",
|
|
111
111
|
"@types/minimist": "^1.2.2",
|
|
112
|
-
"@types/node": "^18.17.
|
|
112
|
+
"@types/node": "^18.17.12",
|
|
113
113
|
"@types/supertest": "^2.0.12",
|
|
114
|
+
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
|
115
|
+
"@typescript-eslint/parser": "^6.5.0",
|
|
114
116
|
"coconfig": "^0.13.3",
|
|
115
|
-
"eslint": "^8.
|
|
116
|
-
"eslint-config-gasbuddy": "^7.2.0",
|
|
117
|
+
"eslint": "^8.48.0",
|
|
117
118
|
"eslint-config-prettier": "^9.0.0",
|
|
119
|
+
"eslint-plugin-import": "^2.28.1",
|
|
118
120
|
"pino-pretty": "^10.2.0",
|
|
119
121
|
"pinst": "^3.0.0",
|
|
120
122
|
"supertest": "^6.3.3",
|
|
121
123
|
"ts-node": "^10.9.1",
|
|
122
124
|
"tsconfig-paths": "^4.2.0",
|
|
123
|
-
"typescript": "^5.
|
|
124
|
-
"vitest": "^0.34.
|
|
125
|
+
"typescript": "^5.2.2",
|
|
126
|
+
"vitest": "^0.34.3"
|
|
125
127
|
},
|
|
126
128
|
"packageManager": "yarn@3.2.3"
|
|
127
129
|
}
|
package/src/config/schema.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface ConfigurationSchema extends Record<string, unknown> {
|
|
|
19
19
|
logHttpRequests?: boolean;
|
|
20
20
|
logRequestBody?: boolean;
|
|
21
21
|
logResponseBody?: boolean;
|
|
22
|
-
}
|
|
22
|
+
};
|
|
23
23
|
routing?: {
|
|
24
24
|
openapi?: boolean;
|
|
25
25
|
// Relative to the *root directory* of the app
|
|
@@ -34,14 +34,14 @@ export interface ConfigurationSchema extends Record<string, unknown> {
|
|
|
34
34
|
bodyParsers?: {
|
|
35
35
|
json?: boolean;
|
|
36
36
|
form?: boolean;
|
|
37
|
-
}
|
|
37
|
+
};
|
|
38
38
|
// Set static.enabled to true to enable static assets to be served
|
|
39
39
|
static?: ConfigurationItemEnabled & {
|
|
40
40
|
// The path relative to the root directory of the app
|
|
41
41
|
path?: string;
|
|
42
42
|
// The path on which to mount the static assets (defaults to /)
|
|
43
43
|
mountPath?: string;
|
|
44
|
-
}
|
|
44
|
+
};
|
|
45
45
|
finalHandlers: {
|
|
46
46
|
// Whether to create and return errors for unhandled routes
|
|
47
47
|
notFound?: boolean;
|
|
@@ -55,12 +55,18 @@ export interface ConfigurationSchema extends Record<string, unknown> {
|
|
|
55
55
|
// information.
|
|
56
56
|
unnest: boolean;
|
|
57
57
|
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
server
|
|
61
|
-
internalPort?: number
|
|
62
|
-
port?: number
|
|
63
|
-
metrics: ConfigurationItemEnabled
|
|
64
|
-
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
server: {
|
|
61
|
+
internalPort?: number;
|
|
62
|
+
port?: number;
|
|
63
|
+
metrics: ConfigurationItemEnabled;
|
|
64
|
+
// To enable HTTPS on the main service, set the key and cert to the
|
|
65
|
+
// actual key material (not the path). Use shortstop file: handler.
|
|
66
|
+
// Note that generally it's better to offload tls termination,
|
|
67
|
+
// but this is useful for dev.
|
|
68
|
+
key?: string;
|
|
69
|
+
certificate?: string;
|
|
70
|
+
};
|
|
65
71
|
connections: Record<string, ServiceConfiguration>;
|
|
66
72
|
}
|
package/src/express-app/app.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from 'assert';
|
|
2
2
|
import http from 'http';
|
|
3
|
+
import https from 'https';
|
|
3
4
|
import path from 'path';
|
|
4
5
|
|
|
5
6
|
import express from 'express';
|
|
@@ -303,18 +304,32 @@ export async function shutdownApp(app: ServiceExpress) {
|
|
|
303
304
|
(logger as pino.Logger).flush?.();
|
|
304
305
|
}
|
|
305
306
|
|
|
307
|
+
function tlsServer<SLocals extends ServiceLocals = ServiceLocals>(
|
|
308
|
+
app: ServiceExpress<SLocals>,
|
|
309
|
+
config: ConfigurationSchema['server'],
|
|
310
|
+
) {
|
|
311
|
+
return https.createServer(
|
|
312
|
+
{
|
|
313
|
+
key: config.key,
|
|
314
|
+
cert: config.certificate,
|
|
315
|
+
},
|
|
316
|
+
app,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
306
320
|
export async function listen<SLocals extends ServiceLocals = ServiceLocals>(
|
|
307
321
|
app: ServiceExpress<SLocals>,
|
|
308
322
|
shutdownHandler?: () => Promise<void>,
|
|
309
323
|
) {
|
|
310
|
-
|
|
324
|
+
const config = app.locals.config.get('server') as Required<ConfigurationSchema['server']>;
|
|
325
|
+
let { port } = config;
|
|
311
326
|
|
|
312
327
|
if (port === 0) {
|
|
313
|
-
port = await findPort(8001);
|
|
328
|
+
port = (await findPort(8001)) as number;
|
|
314
329
|
}
|
|
315
330
|
|
|
316
331
|
const { service, logger } = app.locals;
|
|
317
|
-
const server = http.createServer(app);
|
|
332
|
+
const server = config.certificate ? tlsServer(app, config) : http.createServer(app);
|
|
318
333
|
let shutdownInProgress = false;
|
|
319
334
|
createTerminus(server, {
|
|
320
335
|
timeout: 15000,
|
|
@@ -358,6 +373,10 @@ export async function listen<SLocals extends ServiceLocals = ServiceLocals>(
|
|
|
358
373
|
}
|
|
359
374
|
});
|
|
360
375
|
|
|
376
|
+
server.on('error', (error) => {
|
|
377
|
+
logger.error(error, 'Main service listener error');
|
|
378
|
+
});
|
|
379
|
+
|
|
361
380
|
const metricInfo = (app.locals as AppWithMetrics)[METRICS_KEY] as InternalMetricsInfo;
|
|
362
381
|
delete (app.locals as AppWithMetrics)[METRICS_KEY];
|
|
363
382
|
|
|
@@ -2,11 +2,14 @@ import express from 'express';
|
|
|
2
2
|
import type { Application } from 'express-serve-static-core';
|
|
3
3
|
|
|
4
4
|
import { InternalLocals, ServiceExpress } from '../types';
|
|
5
|
+
import { findPort } from '../development/port-finder';
|
|
5
6
|
|
|
6
7
|
export async function startInternalApp(mainApp: ServiceExpress, port: number) {
|
|
7
8
|
const app = express() as unknown as Application<InternalLocals>;
|
|
8
9
|
app.locals.mainApp = mainApp;
|
|
9
10
|
|
|
11
|
+
const finalPort = port === 0 ? await findPort(3001) : port;
|
|
12
|
+
|
|
10
13
|
app.get('/health', async (req, res) => {
|
|
11
14
|
if (mainApp.locals.service?.healthy) {
|
|
12
15
|
try {
|
|
@@ -21,9 +24,12 @@ export async function startInternalApp(mainApp: ServiceExpress, port: number) {
|
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
const listenPromise = new Promise<void>((accept) => {
|
|
24
|
-
app.locals.server = app.listen(
|
|
27
|
+
app.locals.server = app.listen(finalPort, () => {
|
|
25
28
|
accept();
|
|
26
29
|
});
|
|
30
|
+
app.locals.server.on('error', (error) => {
|
|
31
|
+
mainApp.locals.logger.error(error, 'Internal app server error');
|
|
32
|
+
});
|
|
27
33
|
});
|
|
28
34
|
|
|
29
35
|
await listenPromise;
|