@openapi-typescript-infra/service 3.0.3 → 4.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/CHANGELOG.md +12 -0
- package/build/config/index.d.ts +1 -2
- package/build/config/index.js +6 -4
- package/build/config/index.js.map +1 -1
- package/build/config/schema.d.ts +2 -2
- package/build/express-app/app.js +7 -10
- package/build/express-app/app.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/build/types.d.ts +1 -2
- package/package.json +6 -8
- package/src/config/index.ts +10 -8
- package/src/config/schema.ts +2 -2
- package/src/express-app/app.ts +7 -11
- package/src/types.ts +1 -2
package/build/types.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ import type { Request, Response } from 'express';
|
|
|
8
8
|
import type { Application } from 'express-serve-static-core';
|
|
9
9
|
import type { middleware } from 'express-openapi-validator';
|
|
10
10
|
import type { Meter } from '@opentelemetry/api';
|
|
11
|
-
import { Confit } from '@sesamecare-oss/confit';
|
|
12
11
|
import { ConfigurationSchema } from './config/schema';
|
|
13
12
|
export interface InternalLocals<SLocals extends AnyServiceLocals = ServiceLocals<ConfigurationSchema>> extends Record<string, unknown> {
|
|
14
13
|
server?: Server;
|
|
@@ -19,7 +18,7 @@ export interface ServiceLocals<Config extends ConfigurationSchema = Configuratio
|
|
|
19
18
|
service: Service;
|
|
20
19
|
name: string;
|
|
21
20
|
logger: ServiceLogger;
|
|
22
|
-
config:
|
|
21
|
+
config: Config;
|
|
23
22
|
meter: Meter;
|
|
24
23
|
internalApp: Application<InternalLocals<this>>;
|
|
25
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openapi-typescript-infra/service",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.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": {
|
|
@@ -80,11 +80,10 @@
|
|
|
80
80
|
"@opentelemetry/sdk-node": "^0.43.0",
|
|
81
81
|
"@opentelemetry/sdk-trace-base": "^1.17.1",
|
|
82
82
|
"@opentelemetry/semantic-conventions": "^1.17.1",
|
|
83
|
-
"@sesamecare-oss/confit": "^
|
|
83
|
+
"@sesamecare-oss/confit": "^2.0.0",
|
|
84
84
|
"@sesamecare-oss/opentelemetry-node-metrics": "^1.0.1",
|
|
85
85
|
"cookie-parser": "^1.4.6",
|
|
86
86
|
"dotenv": "^16.3.1",
|
|
87
|
-
"eventsource": "^1.1.2",
|
|
88
87
|
"express": "next",
|
|
89
88
|
"express-openapi-validator": "^5.0.6",
|
|
90
89
|
"glob": "^8.1.0",
|
|
@@ -104,12 +103,11 @@
|
|
|
104
103
|
"@semantic-release/git": "^10.0.1",
|
|
105
104
|
"@semantic-release/release-notes-generator": "^12.0.0",
|
|
106
105
|
"@types/cookie-parser": "^1.4.5",
|
|
107
|
-
"@types/
|
|
108
|
-
"@types/express": "^4.17.19",
|
|
106
|
+
"@types/express": "^4.17.20",
|
|
109
107
|
"@types/glob": "^8.1.0",
|
|
110
|
-
"@types/lodash": "^4.14.
|
|
111
|
-
"@types/minimist": "^1.2.
|
|
112
|
-
"@types/node": "^20.8.
|
|
108
|
+
"@types/lodash": "^4.14.200",
|
|
109
|
+
"@types/minimist": "^1.2.4",
|
|
110
|
+
"@types/node": "^20.8.7",
|
|
113
111
|
"@types/supertest": "^2.0.14",
|
|
114
112
|
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
|
115
113
|
"@typescript-eslint/parser": "^6.8.0",
|
package/src/config/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { BaseConfitSchema, Confit, Factory, confit } from '@sesamecare-oss/confit';
|
|
5
5
|
|
|
6
6
|
import { findPort } from '../development/port-finder';
|
|
7
7
|
|
|
@@ -28,11 +28,11 @@ async function pathExists(f: string) {
|
|
|
28
28
|
async function addDefaultConfiguration<Config extends ConfigurationSchema = ConfigurationSchema>(
|
|
29
29
|
configFactory: Factory<Config>,
|
|
30
30
|
directory: string,
|
|
31
|
-
envConfit: Confit<
|
|
31
|
+
envConfit: Confit<BaseConfitSchema>,
|
|
32
32
|
) {
|
|
33
33
|
const addIfEnv = async (e: (typeof ENVIRONMENTS)[number]) => {
|
|
34
34
|
const c = path.join(directory, `${e}.json`);
|
|
35
|
-
if (envConfit.get(
|
|
35
|
+
if (envConfit.get().env[e] && (await pathExists(c))) {
|
|
36
36
|
configFactory.addDefault(c);
|
|
37
37
|
return true;
|
|
38
38
|
}
|
|
@@ -63,13 +63,13 @@ export async function loadConfiguration<Config extends ConfigurationSchema>({
|
|
|
63
63
|
name,
|
|
64
64
|
configurationDirectories: dirs,
|
|
65
65
|
sourceDirectory,
|
|
66
|
-
}: ServiceConfigurationSpec): Promise<
|
|
66
|
+
}: ServiceConfigurationSpec): Promise<Config> {
|
|
67
67
|
const defaultProtocols = shortstops({ name }, sourceDirectory);
|
|
68
68
|
const specificConfig = dirs[dirs.length - 1];
|
|
69
69
|
|
|
70
70
|
// This confit version just gets us environment info
|
|
71
71
|
const envConfit = await confit({ basedir: specificConfig }).create();
|
|
72
|
-
const configFactory = confit<
|
|
72
|
+
const configFactory = confit<Config>({
|
|
73
73
|
basedir: specificConfig,
|
|
74
74
|
protocols: defaultProtocols,
|
|
75
75
|
});
|
|
@@ -90,17 +90,19 @@ export async function loadConfiguration<Config extends ConfigurationSchema>({
|
|
|
90
90
|
|
|
91
91
|
// Because other things need to know the port we choose, we pick it here if it's
|
|
92
92
|
// configured to auto-select
|
|
93
|
-
const serverConfig = loaded.get(
|
|
93
|
+
const serverConfig = loaded.get().server;
|
|
94
94
|
if (serverConfig.port === 0) {
|
|
95
95
|
const port = (await findPort(8001)) as number;
|
|
96
|
-
loaded.
|
|
96
|
+
const store = loaded.get();
|
|
97
|
+
store.server = store.server || {};
|
|
98
|
+
store.server.port = port;
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
// TODO init other stuff based on config here, such as key management or
|
|
100
102
|
// other cloud-aware shortstop handlers
|
|
101
103
|
|
|
102
104
|
// Not sure why this is necessary, but it is
|
|
103
|
-
return loaded
|
|
105
|
+
return loaded.get();
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
export function insertConfigurationBefore(
|
package/src/config/schema.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BaseConfitSchema } from '@sesamecare-oss/confit';
|
|
2
2
|
import type { Level } from 'pino';
|
|
3
3
|
|
|
4
4
|
export interface ServiceConfiguration {
|
|
@@ -13,7 +13,7 @@ export interface ConfigurationItemEnabled {
|
|
|
13
13
|
enabled?: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export interface ConfigurationSchema extends
|
|
16
|
+
export interface ConfigurationSchema extends BaseConfitSchema {
|
|
17
17
|
trustProxy?: string[];
|
|
18
18
|
logging?: {
|
|
19
19
|
level?: Level;
|
package/src/express-app/app.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { metrics } from '@opentelemetry/api';
|
|
|
10
10
|
import { setupNodeMetrics } from '@sesamecare-oss/opentelemetry-node-metrics';
|
|
11
11
|
import { createTerminus } from '@godaddy/terminus';
|
|
12
12
|
import type { RequestHandler, Response } from 'express';
|
|
13
|
-
import { Confit } from '@sesamecare-oss/confit';
|
|
14
13
|
|
|
15
14
|
import { loadConfiguration } from '../config/index';
|
|
16
15
|
import { openApi } from '../openapi';
|
|
@@ -88,12 +87,12 @@ export async function startApp<
|
|
|
88
87
|
sourceDirectory: path.join(rootDirectory, codepath),
|
|
89
88
|
});
|
|
90
89
|
|
|
91
|
-
const logging = config.
|
|
90
|
+
const logging = config.logging;
|
|
92
91
|
logger.level = logging?.level || 'info';
|
|
93
92
|
|
|
94
93
|
// Concentrate the Typescript ugliness...
|
|
95
94
|
const app = express() as unknown as ServiceExpress<SLocals>;
|
|
96
|
-
const routing = config.
|
|
95
|
+
const routing = config.routing;
|
|
97
96
|
|
|
98
97
|
app.disable('x-powered-by');
|
|
99
98
|
if (routing?.etag !== true) {
|
|
@@ -114,8 +113,8 @@ export async function startApp<
|
|
|
114
113
|
app.locals.meter = metrics.getMeterProvider().getMeter(name);
|
|
115
114
|
setupNodeMetrics(app.locals.meter, {});
|
|
116
115
|
|
|
117
|
-
if (config.
|
|
118
|
-
app.set('trust proxy', config.
|
|
116
|
+
if (config.trustProxy) {
|
|
117
|
+
app.set('trust proxy', config.trustProxy);
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
app.use(loggerMiddleware(app, logging?.logRequestBody, logging?.logResponseBody));
|
|
@@ -220,7 +219,7 @@ export async function startApp<
|
|
|
220
219
|
if (routing?.routes) {
|
|
221
220
|
await loadRoutes(
|
|
222
221
|
app,
|
|
223
|
-
path.resolve(rootDirectory, codepath, config.
|
|
222
|
+
path.resolve(rootDirectory, codepath, config.routing?.routes || 'routes'),
|
|
224
223
|
codePattern,
|
|
225
224
|
);
|
|
226
225
|
}
|
|
@@ -288,10 +287,7 @@ export async function listen<SLocals extends AnyServiceLocals = ServiceLocals<Co
|
|
|
288
287
|
app: ServiceExpress<SLocals>,
|
|
289
288
|
shutdownHandler?: () => Promise<void>,
|
|
290
289
|
) {
|
|
291
|
-
|
|
292
|
-
// otherwise.
|
|
293
|
-
const typedConfig = app.locals.config as unknown as Confit<ConfigurationSchema>;
|
|
294
|
-
const config = typedConfig.get('server') as Required<ConfigurationSchema['server']>;
|
|
290
|
+
const config = app.locals.config.server || {};
|
|
295
291
|
const { port } = config;
|
|
296
292
|
|
|
297
293
|
const { service, logger } = app.locals;
|
|
@@ -348,7 +344,7 @@ export async function listen<SLocals extends AnyServiceLocals = ServiceLocals<Co
|
|
|
348
344
|
const { locals } = app;
|
|
349
345
|
locals.logger.info({ url: url(config, port), service: locals.name }, 'express listening');
|
|
350
346
|
|
|
351
|
-
const serverConfig =
|
|
347
|
+
const serverConfig = app.locals.config.server;
|
|
352
348
|
// Ok now start the internal port if we have one.
|
|
353
349
|
if (serverConfig?.internalPort || serverConfig?.internalPort === 0) {
|
|
354
350
|
startInternalApp(app, serverConfig.internalPort)
|
package/src/types.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type { Request, Response } from 'express';
|
|
|
6
6
|
import type { Application } from 'express-serve-static-core';
|
|
7
7
|
import type { middleware } from 'express-openapi-validator';
|
|
8
8
|
import type { Meter } from '@opentelemetry/api';
|
|
9
|
-
import { Confit } from '@sesamecare-oss/confit';
|
|
10
9
|
|
|
11
10
|
import { ConfigurationSchema } from './config/schema';
|
|
12
11
|
|
|
@@ -26,7 +25,7 @@ export interface ServiceLocals<Config extends ConfigurationSchema = Configuratio
|
|
|
26
25
|
service: Service;
|
|
27
26
|
name: string;
|
|
28
27
|
logger: ServiceLogger;
|
|
29
|
-
config:
|
|
28
|
+
config: Config;
|
|
30
29
|
meter: Meter;
|
|
31
30
|
internalApp: Application<InternalLocals<this>>;
|
|
32
31
|
}
|