vector-framework 1.2.2 → 1.2.3
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/README.md +18 -6
- package/dist/auth/protected.d.ts +4 -4
- package/dist/auth/protected.d.ts.map +1 -1
- package/dist/auth/protected.js +10 -7
- package/dist/auth/protected.js.map +1 -1
- package/dist/cache/manager.d.ts +2 -0
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +21 -4
- package/dist/cache/manager.js.map +1 -1
- package/dist/checkpoint/artifacts/compressor.d.ts +5 -0
- package/dist/checkpoint/artifacts/compressor.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/compressor.js +24 -0
- package/dist/checkpoint/artifacts/compressor.js.map +1 -0
- package/dist/checkpoint/artifacts/decompress-worker.d.ts +2 -0
- package/dist/checkpoint/artifacts/decompress-worker.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/decompress-worker.js +31 -0
- package/dist/checkpoint/artifacts/decompress-worker.js.map +1 -0
- package/dist/checkpoint/artifacts/hasher.d.ts +2 -0
- package/dist/checkpoint/artifacts/hasher.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/hasher.js +7 -0
- package/dist/checkpoint/artifacts/hasher.js.map +1 -0
- package/dist/checkpoint/artifacts/manifest.d.ts +6 -0
- package/dist/checkpoint/artifacts/manifest.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/manifest.js +55 -0
- package/dist/checkpoint/artifacts/manifest.js.map +1 -0
- package/dist/checkpoint/artifacts/materializer.d.ts +16 -0
- package/dist/checkpoint/artifacts/materializer.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/materializer.js +168 -0
- package/dist/checkpoint/artifacts/materializer.js.map +1 -0
- package/dist/checkpoint/artifacts/packager.d.ts +12 -0
- package/dist/checkpoint/artifacts/packager.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/packager.js +82 -0
- package/dist/checkpoint/artifacts/packager.js.map +1 -0
- package/dist/checkpoint/artifacts/repository.d.ts +11 -0
- package/dist/checkpoint/artifacts/repository.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/repository.js +29 -0
- package/dist/checkpoint/artifacts/repository.js.map +1 -0
- package/dist/checkpoint/artifacts/store.d.ts +13 -0
- package/dist/checkpoint/artifacts/store.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/store.js +85 -0
- package/dist/checkpoint/artifacts/store.js.map +1 -0
- package/dist/checkpoint/artifacts/types.d.ts +21 -0
- package/dist/checkpoint/artifacts/types.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/types.js +2 -0
- package/dist/checkpoint/artifacts/types.js.map +1 -0
- package/dist/checkpoint/artifacts/worker-decompressor.d.ts +17 -0
- package/dist/checkpoint/artifacts/worker-decompressor.d.ts.map +1 -0
- package/dist/checkpoint/artifacts/worker-decompressor.js +148 -0
- package/dist/checkpoint/artifacts/worker-decompressor.js.map +1 -0
- package/dist/checkpoint/asset-store.d.ts +10 -0
- package/dist/checkpoint/asset-store.d.ts.map +1 -0
- package/dist/checkpoint/asset-store.js +46 -0
- package/dist/checkpoint/asset-store.js.map +1 -0
- package/dist/checkpoint/bundler.d.ts +15 -0
- package/dist/checkpoint/bundler.d.ts.map +1 -0
- package/dist/checkpoint/bundler.js +45 -0
- package/dist/checkpoint/bundler.js.map +1 -0
- package/dist/checkpoint/cli.d.ts +2 -0
- package/dist/checkpoint/cli.d.ts.map +1 -0
- package/dist/checkpoint/cli.js +157 -0
- package/dist/checkpoint/cli.js.map +1 -0
- package/dist/checkpoint/entrypoint-generator.d.ts +17 -0
- package/dist/checkpoint/entrypoint-generator.d.ts.map +1 -0
- package/dist/checkpoint/entrypoint-generator.js +251 -0
- package/dist/checkpoint/entrypoint-generator.js.map +1 -0
- package/dist/checkpoint/forwarder.d.ts +6 -0
- package/dist/checkpoint/forwarder.d.ts.map +1 -0
- package/dist/checkpoint/forwarder.js +74 -0
- package/dist/checkpoint/forwarder.js.map +1 -0
- package/dist/checkpoint/gateway.d.ts +11 -0
- package/dist/checkpoint/gateway.d.ts.map +1 -0
- package/dist/checkpoint/gateway.js +30 -0
- package/dist/checkpoint/gateway.js.map +1 -0
- package/dist/checkpoint/ipc.d.ts +12 -0
- package/dist/checkpoint/ipc.d.ts.map +1 -0
- package/dist/checkpoint/ipc.js +96 -0
- package/dist/checkpoint/ipc.js.map +1 -0
- package/dist/checkpoint/manager.d.ts +20 -0
- package/dist/checkpoint/manager.d.ts.map +1 -0
- package/dist/checkpoint/manager.js +214 -0
- package/dist/checkpoint/manager.js.map +1 -0
- package/dist/checkpoint/process-manager.d.ts +35 -0
- package/dist/checkpoint/process-manager.d.ts.map +1 -0
- package/dist/checkpoint/process-manager.js +203 -0
- package/dist/checkpoint/process-manager.js.map +1 -0
- package/dist/checkpoint/resolver.d.ts +25 -0
- package/dist/checkpoint/resolver.d.ts.map +1 -0
- package/dist/checkpoint/resolver.js +95 -0
- package/dist/checkpoint/resolver.js.map +1 -0
- package/dist/checkpoint/socket-path.d.ts +2 -0
- package/dist/checkpoint/socket-path.d.ts.map +1 -0
- package/dist/checkpoint/socket-path.js +51 -0
- package/dist/checkpoint/socket-path.js.map +1 -0
- package/dist/checkpoint/types.d.ts +54 -0
- package/dist/checkpoint/types.d.ts.map +1 -0
- package/dist/checkpoint/types.js +2 -0
- package/dist/checkpoint/types.js.map +1 -0
- package/dist/cli/index.js +10 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/option-resolution.d.ts +1 -1
- package/dist/cli/option-resolution.d.ts.map +1 -1
- package/dist/cli/option-resolution.js.map +1 -1
- package/dist/cli.js +3709 -328
- package/dist/core/config-loader.d.ts +1 -0
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/config-loader.js +10 -2
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/router.d.ts +24 -3
- package/dist/core/router.d.ts.map +1 -1
- package/dist/core/router.js +398 -249
- package/dist/core/router.js.map +1 -1
- package/dist/core/server.d.ts +2 -0
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +22 -8
- package/dist/core/server.js.map +1 -1
- package/dist/core/vector.d.ts +3 -0
- package/dist/core/vector.d.ts.map +1 -1
- package/dist/core/vector.js +51 -1
- package/dist/core/vector.js.map +1 -1
- package/dist/dev/route-scanner.d.ts.map +1 -1
- package/dist/dev/route-scanner.js +2 -1
- package/dist/dev/route-scanner.js.map +1 -1
- package/dist/http.d.ts +32 -7
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +144 -13
- package/dist/http.js.map +1 -1
- package/dist/index.cjs +1297 -74
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1296 -73
- package/dist/middleware/manager.d.ts +3 -3
- package/dist/middleware/manager.d.ts.map +1 -1
- package/dist/middleware/manager.js +9 -8
- package/dist/middleware/manager.js.map +1 -1
- package/dist/openapi/docs-ui.d.ts.map +1 -1
- package/dist/openapi/docs-ui.js +1097 -61
- package/dist/openapi/docs-ui.js.map +1 -1
- package/dist/openapi/generator.d.ts +2 -1
- package/dist/openapi/generator.d.ts.map +1 -1
- package/dist/openapi/generator.js +240 -7
- package/dist/openapi/generator.js.map +1 -1
- package/dist/types/index.d.ts +71 -28
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +24 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +3 -2
- package/dist/utils/validation.js.map +1 -1
- package/package.json +2 -1
- package/src/auth/protected.ts +11 -8
- package/src/cache/manager.ts +23 -4
- package/src/checkpoint/artifacts/compressor.ts +30 -0
- package/src/checkpoint/artifacts/decompress-worker.ts +49 -0
- package/src/checkpoint/artifacts/hasher.ts +6 -0
- package/src/checkpoint/artifacts/manifest.ts +72 -0
- package/src/checkpoint/artifacts/materializer.ts +211 -0
- package/src/checkpoint/artifacts/packager.ts +100 -0
- package/src/checkpoint/artifacts/repository.ts +36 -0
- package/src/checkpoint/artifacts/store.ts +102 -0
- package/src/checkpoint/artifacts/types.ts +24 -0
- package/src/checkpoint/artifacts/worker-decompressor.ts +192 -0
- package/src/checkpoint/asset-store.ts +61 -0
- package/src/checkpoint/bundler.ts +64 -0
- package/src/checkpoint/cli.ts +177 -0
- package/src/checkpoint/entrypoint-generator.ts +275 -0
- package/src/checkpoint/forwarder.ts +84 -0
- package/src/checkpoint/gateway.ts +40 -0
- package/src/checkpoint/ipc.ts +107 -0
- package/src/checkpoint/manager.ts +254 -0
- package/src/checkpoint/process-manager.ts +250 -0
- package/src/checkpoint/resolver.ts +124 -0
- package/src/checkpoint/socket-path.ts +61 -0
- package/src/checkpoint/types.ts +63 -0
- package/src/cli/index.ts +11 -2
- package/src/cli/option-resolution.ts +5 -1
- package/src/core/config-loader.ts +11 -2
- package/src/core/router.ts +505 -264
- package/src/core/server.ts +36 -9
- package/src/core/vector.ts +60 -1
- package/src/dev/route-scanner.ts +2 -1
- package/src/http.ts +219 -19
- package/src/index.ts +3 -2
- package/src/middleware/manager.ts +10 -10
- package/src/openapi/docs-ui.ts +1097 -61
- package/src/openapi/generator.ts +265 -6
- package/src/types/index.ts +83 -30
- package/src/utils/validation.ts +5 -3
package/src/openapi/generator.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import type { RegisteredRouteDefinition } from '../core/router';
|
|
2
|
-
import
|
|
2
|
+
import { AuthKind, HttpAuthScheme, OpenApiSecuritySchemeType } from '../types';
|
|
3
|
+
import type {
|
|
4
|
+
OpenAPIAuthOptions,
|
|
5
|
+
OpenAPIInfoOptions,
|
|
6
|
+
OpenAPISecurityScheme,
|
|
7
|
+
RouteSchemaDefinition,
|
|
8
|
+
StandardJSONSchemaCapable,
|
|
9
|
+
} from '../types';
|
|
3
10
|
|
|
4
11
|
type JsonSchema = Record<string, unknown>;
|
|
5
12
|
|
|
6
13
|
export interface OpenAPIGenerationOptions {
|
|
7
14
|
target: string;
|
|
8
15
|
info?: OpenAPIInfoOptions;
|
|
16
|
+
auth?: OpenAPIAuthOptions;
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
export interface OpenAPIGenerationResult {
|
|
@@ -13,6 +21,119 @@ export interface OpenAPIGenerationResult {
|
|
|
13
21
|
warnings: string[];
|
|
14
22
|
}
|
|
15
23
|
|
|
24
|
+
const AUTH_KIND_VALUES = new Set<string>(Object.values(AuthKind));
|
|
25
|
+
const DEFAULT_SECURITY_SCHEME_NAMES: Record<AuthKind, string> = {
|
|
26
|
+
[AuthKind.ApiKey]: 'apiKeyAuth',
|
|
27
|
+
[AuthKind.HttpBasic]: 'basicAuth',
|
|
28
|
+
[AuthKind.HttpBearer]: 'bearerAuth',
|
|
29
|
+
[AuthKind.HttpDigest]: 'digestAuth',
|
|
30
|
+
[AuthKind.OAuth2]: 'oauth2Auth',
|
|
31
|
+
[AuthKind.OpenIdConnect]: 'openIdConnectAuth',
|
|
32
|
+
[AuthKind.MutualTls]: 'mutualTlsAuth',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function isAuthKind(value: unknown): value is AuthKind {
|
|
36
|
+
return typeof value === 'string' && AUTH_KIND_VALUES.has(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function resolveRouteAuthKind(routeAuth: unknown, defaultAuthKind: AuthKind): AuthKind | null {
|
|
40
|
+
if (routeAuth === undefined || routeAuth === false || routeAuth === null) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (routeAuth === true) {
|
|
45
|
+
return defaultAuthKind;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (isAuthKind(routeAuth)) {
|
|
49
|
+
return routeAuth;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Preserve runtime behavior for unexpected truthy auth values.
|
|
53
|
+
return defaultAuthKind;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function resolveSecuritySchemeName(kind: AuthKind, authOptions?: OpenAPIAuthOptions): string {
|
|
57
|
+
const configuredName = authOptions?.securitySchemeNames?.[kind];
|
|
58
|
+
if (typeof configuredName === 'string' && configuredName.trim().length > 0) {
|
|
59
|
+
return configuredName.trim();
|
|
60
|
+
}
|
|
61
|
+
return DEFAULT_SECURITY_SCHEME_NAMES[kind];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function toOpenApiSecurityScheme(kind: AuthKind): OpenAPISecurityScheme {
|
|
65
|
+
switch (kind) {
|
|
66
|
+
case AuthKind.ApiKey:
|
|
67
|
+
return {
|
|
68
|
+
type: OpenApiSecuritySchemeType.ApiKey,
|
|
69
|
+
name: 'X-API-Key',
|
|
70
|
+
in: 'header',
|
|
71
|
+
};
|
|
72
|
+
case AuthKind.HttpBasic:
|
|
73
|
+
return {
|
|
74
|
+
type: OpenApiSecuritySchemeType.Http,
|
|
75
|
+
scheme: HttpAuthScheme.Basic,
|
|
76
|
+
};
|
|
77
|
+
case AuthKind.HttpBearer:
|
|
78
|
+
return {
|
|
79
|
+
type: OpenApiSecuritySchemeType.Http,
|
|
80
|
+
scheme: HttpAuthScheme.Bearer,
|
|
81
|
+
bearerFormat: 'JWT',
|
|
82
|
+
};
|
|
83
|
+
case AuthKind.HttpDigest:
|
|
84
|
+
return {
|
|
85
|
+
type: OpenApiSecuritySchemeType.Http,
|
|
86
|
+
scheme: HttpAuthScheme.Digest,
|
|
87
|
+
};
|
|
88
|
+
case AuthKind.OAuth2:
|
|
89
|
+
return {
|
|
90
|
+
type: OpenApiSecuritySchemeType.OAuth2,
|
|
91
|
+
flows: {
|
|
92
|
+
authorizationCode: {
|
|
93
|
+
authorizationUrl: 'https://example.com/oauth/authorize',
|
|
94
|
+
tokenUrl: 'https://example.com/oauth/token',
|
|
95
|
+
scopes: {},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
case AuthKind.OpenIdConnect:
|
|
100
|
+
return {
|
|
101
|
+
type: OpenApiSecuritySchemeType.OpenIdConnect,
|
|
102
|
+
openIdConnectUrl: 'https://example.com/.well-known/openid-configuration',
|
|
103
|
+
};
|
|
104
|
+
case AuthKind.MutualTls:
|
|
105
|
+
return {
|
|
106
|
+
type: OpenApiSecuritySchemeType.MutualTls,
|
|
107
|
+
};
|
|
108
|
+
default: {
|
|
109
|
+
const exhaustiveCheck: never = kind;
|
|
110
|
+
return exhaustiveCheck;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function resolveSecurityScheme(kind: AuthKind, authOptions?: OpenAPIAuthOptions): OpenAPISecurityScheme {
|
|
116
|
+
const defaultScheme = toOpenApiSecurityScheme(kind);
|
|
117
|
+
const override = authOptions?.securitySchemes?.[kind];
|
|
118
|
+
if (!override) {
|
|
119
|
+
return defaultScheme;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const merged: OpenAPISecurityScheme = {
|
|
123
|
+
...defaultScheme,
|
|
124
|
+
...override,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (isRecord(defaultScheme.flows) && isRecord(override.flows)) {
|
|
128
|
+
merged.flows = {
|
|
129
|
+
...defaultScheme.flows,
|
|
130
|
+
...override.flows,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return merged;
|
|
135
|
+
}
|
|
136
|
+
|
|
16
137
|
function isJSONSchemaCapable(schema: unknown): schema is StandardJSONSchemaCapable {
|
|
17
138
|
const standard = (schema as any)?.['~standard'];
|
|
18
139
|
const converter = standard?.jsonSchema;
|
|
@@ -114,12 +235,89 @@ function isNoBodyResponseStatus(status: string): boolean {
|
|
|
114
235
|
}
|
|
115
236
|
|
|
116
237
|
function getResponseDescription(status: string): string {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
238
|
+
const knownDescriptions: Record<string, string> = {
|
|
239
|
+
'100': 'Continue',
|
|
240
|
+
'101': 'Switching Protocols',
|
|
241
|
+
'102': 'Processing',
|
|
242
|
+
'103': 'Early Hints',
|
|
243
|
+
'200': 'OK',
|
|
244
|
+
'201': 'Created',
|
|
245
|
+
'202': 'Accepted',
|
|
246
|
+
'203': 'Non-Authoritative Information',
|
|
247
|
+
'204': 'No Content',
|
|
248
|
+
'205': 'Reset Content',
|
|
249
|
+
'206': 'Partial Content',
|
|
250
|
+
'207': 'Multi-Status',
|
|
251
|
+
'208': 'Already Reported',
|
|
252
|
+
'226': 'IM Used',
|
|
253
|
+
'300': 'Multiple Choices',
|
|
254
|
+
'301': 'Moved Permanently',
|
|
255
|
+
'302': 'Found',
|
|
256
|
+
'303': 'See Other',
|
|
257
|
+
'304': 'Not Modified',
|
|
258
|
+
'305': 'Use Proxy',
|
|
259
|
+
'307': 'Temporary Redirect',
|
|
260
|
+
'308': 'Permanent Redirect',
|
|
261
|
+
'400': 'Bad Request',
|
|
262
|
+
'401': 'Unauthorized',
|
|
263
|
+
'402': 'Payment Required',
|
|
264
|
+
'403': 'Forbidden',
|
|
265
|
+
'404': 'Not Found',
|
|
266
|
+
'405': 'Method Not Allowed',
|
|
267
|
+
'406': 'Not Acceptable',
|
|
268
|
+
'407': 'Proxy Authentication Required',
|
|
269
|
+
'408': 'Request Timeout',
|
|
270
|
+
'409': 'Conflict',
|
|
271
|
+
'410': 'Gone',
|
|
272
|
+
'411': 'Length Required',
|
|
273
|
+
'412': 'Precondition Failed',
|
|
274
|
+
'413': 'Payload Too Large',
|
|
275
|
+
'414': 'URI Too Long',
|
|
276
|
+
'415': 'Unsupported Media Type',
|
|
277
|
+
'416': 'Range Not Satisfiable',
|
|
278
|
+
'417': 'Expectation Failed',
|
|
279
|
+
'418': "I'm a teapot",
|
|
280
|
+
'421': 'Misdirected Request',
|
|
281
|
+
'422': 'Unprocessable Content',
|
|
282
|
+
'423': 'Locked',
|
|
283
|
+
'424': 'Failed Dependency',
|
|
284
|
+
'425': 'Too Early',
|
|
285
|
+
'426': 'Upgrade Required',
|
|
286
|
+
'428': 'Precondition Required',
|
|
287
|
+
'429': 'Too Many Requests',
|
|
288
|
+
'431': 'Request Header Fields Too Large',
|
|
289
|
+
'451': 'Unavailable For Legal Reasons',
|
|
290
|
+
'500': 'Internal Server Error',
|
|
291
|
+
'501': 'Not Implemented',
|
|
292
|
+
'502': 'Bad Gateway',
|
|
293
|
+
'503': 'Service Unavailable',
|
|
294
|
+
'504': 'Gateway Timeout',
|
|
295
|
+
'505': 'HTTP Version Not Supported',
|
|
296
|
+
'506': 'Variant Also Negotiates',
|
|
297
|
+
'507': 'Insufficient Storage',
|
|
298
|
+
'508': 'Loop Detected',
|
|
299
|
+
'510': 'Not Extended',
|
|
300
|
+
'511': 'Network Authentication Required',
|
|
301
|
+
};
|
|
302
|
+
if (knownDescriptions[status]) {
|
|
303
|
+
return knownDescriptions[status];
|
|
304
|
+
}
|
|
305
|
+
|
|
120
306
|
const numericStatus = Number(status);
|
|
121
307
|
if (Number.isInteger(numericStatus) && numericStatus >= 100 && numericStatus < 200) {
|
|
122
|
-
return 'Informational';
|
|
308
|
+
return 'Informational Response';
|
|
309
|
+
}
|
|
310
|
+
if (Number.isInteger(numericStatus) && numericStatus >= 200 && numericStatus < 300) {
|
|
311
|
+
return 'Successful Response';
|
|
312
|
+
}
|
|
313
|
+
if (Number.isInteger(numericStatus) && numericStatus >= 300 && numericStatus < 400) {
|
|
314
|
+
return 'Redirection';
|
|
315
|
+
}
|
|
316
|
+
if (Number.isInteger(numericStatus) && numericStatus >= 400 && numericStatus < 500) {
|
|
317
|
+
return 'Client Error';
|
|
318
|
+
}
|
|
319
|
+
if (Number.isInteger(numericStatus) && numericStatus >= 500 && numericStatus < 600) {
|
|
320
|
+
return 'Server Error';
|
|
123
321
|
}
|
|
124
322
|
return 'OK';
|
|
125
323
|
}
|
|
@@ -648,6 +846,8 @@ export function generateOpenAPIDocument(
|
|
|
648
846
|
): OpenAPIGenerationResult {
|
|
649
847
|
const warnings: string[] = [];
|
|
650
848
|
const paths: Record<string, Record<string, unknown>> = {};
|
|
849
|
+
const defaultAuthKind = AuthKind.HttpBearer;
|
|
850
|
+
const usedAuthKinds = new Set<AuthKind>();
|
|
651
851
|
|
|
652
852
|
for (const route of routes) {
|
|
653
853
|
if (route.options.expose === false) continue;
|
|
@@ -661,15 +861,64 @@ export function generateOpenAPIDocument(
|
|
|
661
861
|
operationId: createOperationId(method, openapiPath),
|
|
662
862
|
tags: [route.options.schema?.tag || inferTagFromPath(route.path)],
|
|
663
863
|
};
|
|
864
|
+
if (typeof route.options.schema?.summary === 'string' && route.options.schema.summary.trim()) {
|
|
865
|
+
operation.summary = route.options.schema.summary.trim();
|
|
866
|
+
}
|
|
867
|
+
const routeSchemaDescription =
|
|
868
|
+
typeof route.options.schema?.description === 'string' && route.options.schema.description.trim()
|
|
869
|
+
? route.options.schema.description.trim()
|
|
870
|
+
: typeof route.options.schema?.descrition === 'string' && route.options.schema.descrition.trim()
|
|
871
|
+
? route.options.schema.descrition.trim()
|
|
872
|
+
: undefined;
|
|
873
|
+
if (routeSchemaDescription) {
|
|
874
|
+
operation.description = routeSchemaDescription;
|
|
875
|
+
}
|
|
876
|
+
if (route.options.deprecated === true) {
|
|
877
|
+
operation.deprecated = true;
|
|
878
|
+
}
|
|
879
|
+
const routeAuthKind = resolveRouteAuthKind(route.options.auth, defaultAuthKind);
|
|
880
|
+
if (routeAuthKind) {
|
|
881
|
+
usedAuthKinds.add(routeAuthKind);
|
|
882
|
+
const securitySchemeName = resolveSecuritySchemeName(routeAuthKind, options.auth);
|
|
883
|
+
operation.security = [{ [securitySchemeName]: [] }];
|
|
884
|
+
}
|
|
664
885
|
|
|
665
886
|
const inputJSONSchema = convertInputSchema(route.path, route.options.schema?.input, options.target, warnings);
|
|
666
887
|
|
|
667
888
|
if (inputJSONSchema) {
|
|
889
|
+
if (!operation.summary && typeof inputJSONSchema.title === 'string' && inputJSONSchema.title.trim()) {
|
|
890
|
+
operation.summary = inputJSONSchema.title.trim();
|
|
891
|
+
}
|
|
892
|
+
if (
|
|
893
|
+
!operation.description &&
|
|
894
|
+
typeof inputJSONSchema.description === 'string' &&
|
|
895
|
+
inputJSONSchema.description.trim()
|
|
896
|
+
) {
|
|
897
|
+
operation.description = inputJSONSchema.description.trim();
|
|
898
|
+
}
|
|
668
899
|
addStructuredInputToOperation(operation, inputJSONSchema);
|
|
669
900
|
}
|
|
670
901
|
addMissingPathParameters(operation, route.path);
|
|
671
902
|
|
|
672
903
|
addOutputSchemasToOperation(operation, route.path, route.options.schema || {}, options.target, warnings);
|
|
904
|
+
if (!operation.summary || !operation.description) {
|
|
905
|
+
const responseEntries = Object.values(operation.responses || {}) as any[];
|
|
906
|
+
for (const response of responseEntries) {
|
|
907
|
+
const responseSchema = response?.content?.['application/json']?.schema;
|
|
908
|
+
if (!responseSchema || typeof responseSchema !== 'object') continue;
|
|
909
|
+
if (!operation.summary && typeof responseSchema.title === 'string' && responseSchema.title.trim()) {
|
|
910
|
+
operation.summary = responseSchema.title.trim();
|
|
911
|
+
}
|
|
912
|
+
if (
|
|
913
|
+
!operation.description &&
|
|
914
|
+
typeof responseSchema.description === 'string' &&
|
|
915
|
+
responseSchema.description.trim()
|
|
916
|
+
) {
|
|
917
|
+
operation.description = responseSchema.description.trim();
|
|
918
|
+
}
|
|
919
|
+
if (operation.summary && operation.description) break;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
673
922
|
|
|
674
923
|
paths[openapiPath] ||= {};
|
|
675
924
|
paths[openapiPath][method] = operation;
|
|
@@ -677,7 +926,7 @@ export function generateOpenAPIDocument(
|
|
|
677
926
|
|
|
678
927
|
const openapiVersion = options.target === 'openapi-3.0' ? '3.0.3' : '3.1.0';
|
|
679
928
|
|
|
680
|
-
const document = {
|
|
929
|
+
const document: Record<string, unknown> = {
|
|
681
930
|
openapi: openapiVersion,
|
|
682
931
|
info: {
|
|
683
932
|
title: options.info?.title || 'Vector API',
|
|
@@ -686,6 +935,16 @@ export function generateOpenAPIDocument(
|
|
|
686
935
|
},
|
|
687
936
|
paths,
|
|
688
937
|
};
|
|
938
|
+
if (usedAuthKinds.size > 0) {
|
|
939
|
+
const securitySchemes: Record<string, OpenAPISecurityScheme> = {};
|
|
940
|
+
for (const authKind of usedAuthKinds) {
|
|
941
|
+
const name = resolveSecuritySchemeName(authKind, options.auth);
|
|
942
|
+
securitySchemes[name] = resolveSecurityScheme(authKind, options.auth);
|
|
943
|
+
}
|
|
944
|
+
document.components = {
|
|
945
|
+
securitySchemes,
|
|
946
|
+
};
|
|
947
|
+
}
|
|
689
948
|
|
|
690
949
|
return {
|
|
691
950
|
document,
|
package/src/types/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { StandardJSONSchemaV1, StandardSchemaV1, StandardTypedV1 } from './standard-schema';
|
|
2
2
|
import type { Server } from 'bun';
|
|
3
|
+
import type { CheckpointConfig } from '../checkpoint/types';
|
|
3
4
|
|
|
4
5
|
// Default AuthUser type - users can override this with their own type
|
|
5
6
|
export interface DefaultAuthUser {
|
|
@@ -14,7 +15,6 @@ export interface DefaultAuthUser {
|
|
|
14
15
|
// Users can override any of these types without breaking changes
|
|
15
16
|
export interface VectorTypes {
|
|
16
17
|
auth?: any; // Custom auth user type
|
|
17
|
-
context?: any; // Custom request context (future)
|
|
18
18
|
cache?: any; // Custom cache value type (future)
|
|
19
19
|
metadata?: any; // Custom metadata type (future)
|
|
20
20
|
}
|
|
@@ -22,7 +22,6 @@ export interface VectorTypes {
|
|
|
22
22
|
// Default types
|
|
23
23
|
export interface DefaultVectorTypes extends VectorTypes {
|
|
24
24
|
auth: DefaultAuthUser;
|
|
25
|
-
context: Record<string, any>;
|
|
26
25
|
cache: any;
|
|
27
26
|
metadata: Record<string, any>;
|
|
28
27
|
}
|
|
@@ -30,8 +29,6 @@ export interface DefaultVectorTypes extends VectorTypes {
|
|
|
30
29
|
// Type helpers
|
|
31
30
|
export type GetAuthType<T extends VectorTypes> = T['auth'] extends undefined ? DefaultAuthUser : T['auth'];
|
|
32
31
|
|
|
33
|
-
export type GetContextType<T extends VectorTypes> = T['context'] extends undefined ? Record<string, any> : T['context'];
|
|
34
|
-
|
|
35
32
|
export type GetCacheType<T extends VectorTypes> = T['cache'] extends undefined ? any : T['cache'];
|
|
36
33
|
|
|
37
34
|
export type GetMetadataType<T extends VectorTypes> = T['metadata'] extends undefined
|
|
@@ -41,11 +38,7 @@ export type GetMetadataType<T extends VectorTypes> = T['metadata'] extends undef
|
|
|
41
38
|
// Legacy support - keep AuthUser for backward compatibility
|
|
42
39
|
export type AuthUser = DefaultAuthUser;
|
|
43
40
|
|
|
44
|
-
type
|
|
45
|
-
type DefaultParamsShape = Record<string, string>;
|
|
46
|
-
type DefaultCookiesShape = Record<string, string>;
|
|
47
|
-
|
|
48
|
-
type BaseVectorRequest = Omit<Request, 'body' | 'json' | 'text' | 'formData' | 'arrayBuffer' | 'blob'>;
|
|
41
|
+
type BaseVectorRequest = Request;
|
|
49
42
|
|
|
50
43
|
type InferValidatedSection<TValidatedInput, TKey extends string, TFallback> = [TValidatedInput] extends [undefined]
|
|
51
44
|
? TFallback
|
|
@@ -56,27 +49,35 @@ type InferValidatedSection<TValidatedInput, TKey extends string, TFallback> = [T
|
|
|
56
49
|
: TFallback;
|
|
57
50
|
|
|
58
51
|
type InferValidatedInputValue<TValidatedInput> = [TValidatedInput] extends [undefined] ? unknown : TValidatedInput;
|
|
52
|
+
type ValidatedInputField<TValidatedInput> = [TValidatedInput] extends [undefined]
|
|
53
|
+
? { validatedInput?: InferValidatedInputValue<TValidatedInput> }
|
|
54
|
+
: { validatedInput: InferValidatedInputValue<TValidatedInput> };
|
|
59
55
|
|
|
60
56
|
export type BunRouteHandler = (req: Request) => Response | Promise<Response>;
|
|
61
57
|
export type BunMethodMap = Record<string, BunRouteHandler>;
|
|
62
58
|
export type BunRouteTable = Record<string, BunMethodMap | Response>;
|
|
63
59
|
export type LegacyRouteEntry = [string, RegExp, [BunRouteHandler, ...BunRouteHandler[]], string?];
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
type VectorRequestTypeBrand<TTypes extends VectorTypes, TValidatedInput> = {
|
|
62
|
+
readonly __vectorTypesBrand__?: TTypes;
|
|
63
|
+
readonly __validatedInputBrand__?: TValidatedInput;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type VectorRequest<
|
|
67
|
+
TTypes extends VectorTypes = DefaultVectorTypes,
|
|
68
|
+
TValidatedInput = undefined,
|
|
69
|
+
> = BaseVectorRequest & VectorRequestTypeBrand<TTypes, TValidatedInput>;
|
|
70
|
+
|
|
71
|
+
export type VectorContext<TTypes extends VectorTypes = DefaultVectorTypes, TValidatedInput = undefined> = {
|
|
72
|
+
request: VectorRequest<TTypes, TValidatedInput>;
|
|
67
73
|
authUser?: GetAuthType<TTypes>;
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
metadata: GetMetadataType<TTypes>;
|
|
75
|
+
params: InferValidatedSection<TValidatedInput, 'params', Record<string, string>>;
|
|
76
|
+
query: InferValidatedSection<TValidatedInput, 'query', Record<string, string | string[]>>;
|
|
77
|
+
cookies: InferValidatedSection<TValidatedInput, 'cookies', Record<string, string>>;
|
|
70
78
|
content?: InferValidatedSection<TValidatedInput, 'body', any>;
|
|
71
|
-
body?: InferValidatedSection<TValidatedInput, 'body', any>;
|
|
72
|
-
params?: InferValidatedSection<TValidatedInput, 'params', DefaultParamsShape>;
|
|
73
|
-
query: InferValidatedSection<TValidatedInput, 'query', DefaultQueryShape>;
|
|
74
|
-
headers: Headers;
|
|
75
|
-
cookies?: InferValidatedSection<TValidatedInput, 'cookies', DefaultCookiesShape>;
|
|
76
|
-
validatedInput?: InferValidatedInputValue<TValidatedInput>;
|
|
77
|
-
startTime?: number;
|
|
78
79
|
[key: string]: any;
|
|
79
|
-
}
|
|
80
|
+
} & ValidatedInputField<TValidatedInput>;
|
|
80
81
|
|
|
81
82
|
export interface CacheOptions {
|
|
82
83
|
key?: string;
|
|
@@ -97,6 +98,52 @@ export interface RouteSchemaDefinition<
|
|
|
97
98
|
input?: TInput;
|
|
98
99
|
output?: TOutput;
|
|
99
100
|
tag?: string;
|
|
101
|
+
summary?: string;
|
|
102
|
+
description?: string;
|
|
103
|
+
descrition?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export enum OpenApiSecuritySchemeType {
|
|
107
|
+
ApiKey = 'apiKey',
|
|
108
|
+
Http = 'http',
|
|
109
|
+
MutualTls = 'mutualTLS',
|
|
110
|
+
OAuth2 = 'oauth2',
|
|
111
|
+
OpenIdConnect = 'openIdConnect',
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export enum HttpAuthScheme {
|
|
115
|
+
Basic = 'basic',
|
|
116
|
+
Bearer = 'bearer',
|
|
117
|
+
Digest = 'digest',
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export enum AuthKind {
|
|
121
|
+
ApiKey = 'ApiKey',
|
|
122
|
+
HttpBasic = 'HttpBasic',
|
|
123
|
+
HttpBearer = 'HttpBearer',
|
|
124
|
+
HttpDigest = 'HttpDigest',
|
|
125
|
+
OAuth2 = 'OAuth2',
|
|
126
|
+
OpenIdConnect = 'OpenIdConnect',
|
|
127
|
+
MutualTls = 'MutualTls',
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export type RouteAuthOption = boolean | AuthKind;
|
|
131
|
+
|
|
132
|
+
export interface OpenAPISecurityScheme {
|
|
133
|
+
type: OpenApiSecuritySchemeType | ({} & string);
|
|
134
|
+
description?: string;
|
|
135
|
+
name?: string;
|
|
136
|
+
in?: 'query' | 'header' | 'cookie';
|
|
137
|
+
scheme?: string;
|
|
138
|
+
bearerFormat?: string;
|
|
139
|
+
flows?: Record<string, unknown>;
|
|
140
|
+
openIdConnectUrl?: string;
|
|
141
|
+
[key: string]: unknown;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface OpenAPIAuthOptions {
|
|
145
|
+
securitySchemeNames?: Partial<Record<AuthKind, string>>;
|
|
146
|
+
securitySchemes?: Partial<Record<AuthKind, OpenAPISecurityScheme>>;
|
|
100
147
|
}
|
|
101
148
|
|
|
102
149
|
export type InferStandardSchemaInput<TSchema extends StandardRouteSchema> = StandardSchemaV1.InferInput<TSchema>;
|
|
@@ -113,8 +160,9 @@ export type InferRouteInputFromSchemaDefinition<TSchemaDef extends RouteSchemaDe
|
|
|
113
160
|
export interface RouteOptions<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
114
161
|
method: string;
|
|
115
162
|
path: string;
|
|
116
|
-
auth?:
|
|
163
|
+
auth?: RouteAuthOption;
|
|
117
164
|
expose?: boolean; // defaults to true
|
|
165
|
+
deprecated?: boolean; // OpenAPI operation.deprecated flag
|
|
118
166
|
cache?: CacheOptions | number;
|
|
119
167
|
rawRequest?: boolean;
|
|
120
168
|
validate?: boolean; // defaults to validating schema.input unless false
|
|
@@ -125,7 +173,7 @@ export interface RouteOptions<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
125
173
|
}
|
|
126
174
|
|
|
127
175
|
export interface RouteBooleanDefaults {
|
|
128
|
-
auth?:
|
|
176
|
+
auth?: RouteAuthOption;
|
|
129
177
|
expose?: boolean;
|
|
130
178
|
rawRequest?: boolean;
|
|
131
179
|
validate?: boolean;
|
|
@@ -138,7 +186,7 @@ export interface VectorDefaults {
|
|
|
138
186
|
|
|
139
187
|
// Legacy config interface - will be deprecated
|
|
140
188
|
export interface VectorConfig<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
141
|
-
port?: number;
|
|
189
|
+
port?: number | string;
|
|
142
190
|
hostname?: string;
|
|
143
191
|
reusePort?: boolean;
|
|
144
192
|
development?: boolean;
|
|
@@ -153,6 +201,7 @@ export interface VectorConfig<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
153
201
|
openapi?: OpenAPIOptions | boolean;
|
|
154
202
|
startup?: StartupHandler;
|
|
155
203
|
shutdown?: ShutdownHandler;
|
|
204
|
+
checkpoint?: CheckpointConfig;
|
|
156
205
|
}
|
|
157
206
|
|
|
158
207
|
export interface StartVectorContext {
|
|
@@ -181,7 +230,7 @@ export interface StartedVectorApp<TTypes extends VectorTypes = DefaultVectorType
|
|
|
181
230
|
// New config-driven schema - flat structure
|
|
182
231
|
export interface VectorConfigSchema<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
183
232
|
// Server configuration
|
|
184
|
-
port?: number;
|
|
233
|
+
port?: number | string;
|
|
185
234
|
hostname?: string;
|
|
186
235
|
reusePort?: boolean;
|
|
187
236
|
development?: boolean;
|
|
@@ -208,6 +257,9 @@ export interface VectorConfigSchema<TTypes extends VectorTypes = DefaultVectorTy
|
|
|
208
257
|
startup?: StartupHandler;
|
|
209
258
|
shutdown?: ShutdownHandler;
|
|
210
259
|
|
|
260
|
+
// Checkpoints
|
|
261
|
+
checkpoint?: CheckpointConfig;
|
|
262
|
+
|
|
211
263
|
// Custom types for TypeScript
|
|
212
264
|
types?: VectorTypes;
|
|
213
265
|
}
|
|
@@ -239,15 +291,16 @@ export interface OpenAPIOptions {
|
|
|
239
291
|
target?: 'openapi-3.0' | 'draft-2020-12' | 'draft-07' | ({} & string);
|
|
240
292
|
docs?: boolean | OpenAPIDocsOptions;
|
|
241
293
|
info?: OpenAPIInfoOptions;
|
|
294
|
+
auth?: OpenAPIAuthOptions;
|
|
242
295
|
}
|
|
243
296
|
|
|
244
297
|
export type BeforeMiddlewareHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
|
|
245
|
-
|
|
246
|
-
) => Promise<
|
|
298
|
+
context: VectorContext<TTypes>
|
|
299
|
+
) => Promise<void | Response> | void | Response;
|
|
247
300
|
|
|
248
301
|
export type AfterMiddlewareHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
|
|
249
302
|
response: Response,
|
|
250
|
-
|
|
303
|
+
context: VectorContext<TTypes>
|
|
251
304
|
) => Promise<Response> | Response;
|
|
252
305
|
export type MiddlewareHandler = BeforeMiddlewareHandler | AfterMiddlewareHandler;
|
|
253
306
|
|
|
@@ -255,11 +308,11 @@ export type StartupHandler = () => Promise<void> | void;
|
|
|
255
308
|
export type ShutdownHandler = () => Promise<void> | void;
|
|
256
309
|
|
|
257
310
|
export type RouteHandler<TTypes extends VectorTypes = DefaultVectorTypes, TValidatedInput = undefined> = (
|
|
258
|
-
|
|
311
|
+
context: VectorContext<TTypes, TValidatedInput>
|
|
259
312
|
) => Promise<any> | any;
|
|
260
313
|
|
|
261
314
|
export type ProtectedHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
|
|
262
|
-
|
|
315
|
+
context: VectorContext<TTypes>
|
|
263
316
|
) => Promise<GetAuthType<TTypes>> | GetAuthType<TTypes>;
|
|
264
317
|
|
|
265
318
|
export type CacheHandler = (key: string, factory: () => Promise<any>, ttl: number) => Promise<any>;
|
package/src/utils/validation.ts
CHANGED
|
@@ -20,16 +20,18 @@ export function validateConfig(config: VectorConfig): VectorConfig {
|
|
|
20
20
|
return validatedConfig;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function validatePort(port?: number): number {
|
|
23
|
+
function validatePort(port?: number | string): number {
|
|
24
24
|
if (port === undefined) {
|
|
25
25
|
return DEFAULT_CONFIG.PORT;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
const normalizedPort = Number(port);
|
|
29
|
+
|
|
30
|
+
if (!Number.isInteger(normalizedPort) || normalizedPort < 1 || normalizedPort > 65535) {
|
|
29
31
|
throw new Error(`Invalid port: ${port}. Port must be between 1 and 65535.`);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
return
|
|
34
|
+
return normalizedPort;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function validateCorsOptions(cors: CorsOptions | boolean): CorsOptions | undefined {
|