@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
package/src/types.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Server } from 'http';
|
|
2
|
+
|
|
3
|
+
import type pino from 'pino';
|
|
4
|
+
import type { Request, Response } from 'express';
|
|
5
|
+
import type { Application } from 'express-serve-static-core';
|
|
6
|
+
import type { middleware } from 'express-openapi-validator';
|
|
7
|
+
import type { Meter, MeterProvider } from '@opentelemetry/api-metrics';
|
|
8
|
+
|
|
9
|
+
import type { ConfigStore } from './config/types';
|
|
10
|
+
|
|
11
|
+
export interface InternalLocals extends Record<string, unknown> {
|
|
12
|
+
server?: Server;
|
|
13
|
+
meterProvider: MeterProvider;
|
|
14
|
+
mainApp: ServiceExpress;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ServiceLogger = pino.BaseLogger & Pick<pino.Logger, 'isLevelEnabled'>;
|
|
18
|
+
|
|
19
|
+
// Vanilla express wants this to extend Record<string, any> but this is a mistake
|
|
20
|
+
// because you lose type checking on it, even though I get that underneath it truly
|
|
21
|
+
// is Record<string, any>
|
|
22
|
+
export interface ServiceLocals {
|
|
23
|
+
service: Service;
|
|
24
|
+
name: string;
|
|
25
|
+
logger: ServiceLogger;
|
|
26
|
+
config: ConfigStore;
|
|
27
|
+
meter: Meter;
|
|
28
|
+
internalApp: Application<InternalLocals>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface RequestLocals {
|
|
32
|
+
// Set this to true during the request "attachment" and if there is a body,
|
|
33
|
+
// it will be set to the buffer before API and route handlers run.
|
|
34
|
+
rawBody?: Buffer | true;
|
|
35
|
+
logger: ServiceLogger;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ServiceExpress<Locals extends ServiceLocals = ServiceLocals> = Application<Locals>;
|
|
39
|
+
export type RequestWithApp<Locals extends ServiceLocals = ServiceLocals> = Omit<Request, 'app'> & {
|
|
40
|
+
app: Application<Locals>;
|
|
41
|
+
};
|
|
42
|
+
export type ResponseFromApp<
|
|
43
|
+
ResBody = unknown,
|
|
44
|
+
RLocals extends RequestLocals = RequestLocals,
|
|
45
|
+
> = Response<ResBody, RLocals>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This is the core type you need to implement to provide a service
|
|
49
|
+
*/
|
|
50
|
+
export interface Service<
|
|
51
|
+
SLocals extends ServiceLocals = ServiceLocals,
|
|
52
|
+
RLocals extends RequestLocals = RequestLocals,
|
|
53
|
+
> {
|
|
54
|
+
name?: string;
|
|
55
|
+
|
|
56
|
+
// Modify options used for application start
|
|
57
|
+
configure?: (
|
|
58
|
+
startOptions: ServiceStartOptions<SLocals, RLocals>,
|
|
59
|
+
options: ServiceOptions,
|
|
60
|
+
) => ServiceOptions;
|
|
61
|
+
|
|
62
|
+
start(app: ServiceExpress<SLocals>): void | Promise<void>;
|
|
63
|
+
stop?: (app: ServiceExpress<SLocals>) => void | Promise<void>;
|
|
64
|
+
|
|
65
|
+
healthy?: (app: ServiceExpress<SLocals>) => boolean | Promise<boolean>;
|
|
66
|
+
|
|
67
|
+
// This runs as middleware right BEFORE the body parsers.
|
|
68
|
+
// If you want to run AFTER the body parsers, the current
|
|
69
|
+
// way to do that would be via /routes/index.ts and router.use()
|
|
70
|
+
// in that file.
|
|
71
|
+
onRequest?(req: RequestWithApp<SLocals>, res: Response<unknown, RLocals>): void | Promise<void>;
|
|
72
|
+
|
|
73
|
+
// This runs after body parsing but before routing
|
|
74
|
+
authorize?(req: RequestWithApp<SLocals>, res: Response<unknown, RLocals>): boolean | Promise<boolean>;
|
|
75
|
+
|
|
76
|
+
// Add or redact any fields for logging. Note this will be called twice per request,
|
|
77
|
+
// once at the start and once at the end. Modify the values directly.
|
|
78
|
+
getLogFields?(req: RequestWithApp<SLocals>, values: Record<string, string | string[] | number | undefined>): void;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type ServiceFactory<
|
|
82
|
+
SLocals extends ServiceLocals = ServiceLocals,
|
|
83
|
+
RLocals extends RequestLocals = RequestLocals,
|
|
84
|
+
> = () => Service<SLocals, RLocals>;
|
|
85
|
+
|
|
86
|
+
export interface ServiceStartOptions<
|
|
87
|
+
SLocals extends ServiceLocals = ServiceLocals,
|
|
88
|
+
RLocals extends RequestLocals = RequestLocals,
|
|
89
|
+
> {
|
|
90
|
+
name: string;
|
|
91
|
+
rootDirectory: string;
|
|
92
|
+
|
|
93
|
+
// Defaults to "build", but can be set to "src" to run off non-built source
|
|
94
|
+
codepath?: 'build' | 'src';
|
|
95
|
+
|
|
96
|
+
// NOTE: if you use this, you need to cast it because of a Typescript error:
|
|
97
|
+
// https://github.com/microsoft/TypeScript/issues/22229
|
|
98
|
+
// locals: { stuff } as Partial<MyLocals>
|
|
99
|
+
locals?: Partial<SLocals>;
|
|
100
|
+
|
|
101
|
+
// And finally, the function that creates the service instance
|
|
102
|
+
service: () => Service<SLocals, RLocals>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface DelayLoadServiceStartOptions extends Omit<ServiceStartOptions, 'service'> {
|
|
106
|
+
service: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Handled by service.configure
|
|
110
|
+
export interface ServiceOptions {
|
|
111
|
+
// If you need multiple configuration directories, pass them here
|
|
112
|
+
// in the desired order (later trumps earlier)
|
|
113
|
+
configurationDirectories: string[];
|
|
114
|
+
|
|
115
|
+
// Add or control OpenAPI options such as security handlers
|
|
116
|
+
openApiOptions?: Parameters<typeof middleware>[0];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ServiceLike<SLocals extends ServiceLocals = ServiceLocals> {
|
|
120
|
+
locals: SLocals;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* This type should be used (or extended) to pass "context"
|
|
125
|
+
* into functions not directly wired into the Express request
|
|
126
|
+
* handling flow. It will allow "synthetic" requests to be
|
|
127
|
+
* easily constructed without depending on things they should not,
|
|
128
|
+
* like query strings or body or similar. Most often, you want the
|
|
129
|
+
* logger.
|
|
130
|
+
*/
|
|
131
|
+
export interface RequestLike<
|
|
132
|
+
SLocals extends ServiceLocals = ServiceLocals,
|
|
133
|
+
RLocals extends RequestLocals = RequestLocals,
|
|
134
|
+
> {
|
|
135
|
+
app: ServiceLike<SLocals>;
|
|
136
|
+
res: {
|
|
137
|
+
locals: RLocals;
|
|
138
|
+
};
|
|
139
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": [
|
|
3
|
+
"@types/**/*",
|
|
4
|
+
"src/**/*",
|
|
5
|
+
"__tests__/**/*",
|
|
6
|
+
"__mocks__/**/*",
|
|
7
|
+
"coconfig.ts"
|
|
8
|
+
],
|
|
9
|
+
"exclude": [
|
|
10
|
+
"node_modules",
|
|
11
|
+
"build"
|
|
12
|
+
],
|
|
13
|
+
"ts-node": {
|
|
14
|
+
"transpileOnly": true,
|
|
15
|
+
"files": true
|
|
16
|
+
},
|
|
17
|
+
"compilerOptions": {
|
|
18
|
+
"lib": [
|
|
19
|
+
"ES2022",
|
|
20
|
+
"DOM"
|
|
21
|
+
],
|
|
22
|
+
"module": "CommonJS",
|
|
23
|
+
"target": "ES2022",
|
|
24
|
+
"declaration": true,
|
|
25
|
+
"sourceMap": true,
|
|
26
|
+
"outDir": "./build",
|
|
27
|
+
"incremental": true,
|
|
28
|
+
"isolatedModules": true,
|
|
29
|
+
"strict": true,
|
|
30
|
+
"moduleResolution": "NodeNext",
|
|
31
|
+
"baseUrl": "./src",
|
|
32
|
+
"allowSyntheticDefaultImports": true,
|
|
33
|
+
"esModuleInterop": true,
|
|
34
|
+
"experimentalDecorators": true
|
|
35
|
+
}
|
|
36
|
+
}
|