@zudojs/openapi 0.0.1 → 1.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/LICENSE +21 -0
- package/README.md +327 -21
- package/dist/index.d.ts +26 -21
- package/dist/index.js +31 -13
- package/dist/openApiComponents/index.d.ts +2 -2
- package/dist/openApiComponents/index.js +1 -1
- package/dist/openApiConstants/index.d.ts +1 -1
- package/dist/openApiConstants/index.js +1 -1
- package/dist/openApiConstants/openApiConstants.core.d.ts +15 -3
- package/dist/openApiConstants/openApiConstants.core.js +22 -3
- package/dist/openApiDocument/index.d.ts +1 -1
- package/dist/openApiDocument/index.js +1 -1
- package/dist/openApiDocument/openApiDocument.builder.d.ts +39 -52
- package/dist/openApiDocument/openApiDocument.builder.js +73 -72
- package/dist/openApiErrors/index.d.ts +2 -2
- package/dist/openApiErrors/index.js +2 -1
- package/dist/openApiErrors/openApiError.base.d.ts +9 -0
- package/dist/openApiErrors/openApiError.base.js +7 -0
- package/dist/openApiErrors/openApiError.types.d.ts +34 -14
- package/dist/openApiErrors/openApiError.types.js +83 -35
- package/dist/openApiHttp/index.d.ts +2 -2
- package/dist/openApiHttp/index.js +2 -2
- package/dist/openApiHttp/openApiHttpAdapter.core.d.ts +127 -25
- package/dist/openApiHttp/openApiHttpAdapter.core.js +212 -16
- package/dist/openApiRegistry/openApiRegistry.core.d.ts +38 -5
- package/dist/openApiRegistry/openApiRegistry.core.js +167 -66
- package/dist/openApiRegistry/openApiRegistry.type.d.ts +18 -13
- package/dist/openApiRegistry/openApiRegistry.type.js +1 -2
- package/dist/openApiRouting/index.d.ts +2 -2
- package/dist/openApiRouting/index.js +1 -1
- package/dist/openApiRouting/routeConverter.core.d.ts +25 -7
- package/dist/openApiRouting/routeConverter.core.js +104 -58
- package/dist/openApiRouting/routeMetadata.type.d.ts +40 -17
- package/dist/openApiRouting/routeMetadata.type.js +9 -0
- package/dist/openApiRouting/routeScanner.core.d.ts +17 -47
- package/dist/openApiRouting/routeScanner.core.js +40 -55
- package/dist/openApiSchema/index.d.ts +4 -4
- package/dist/openApiSchema/index.js +2 -2
- package/dist/openApiSchema/references.core.d.ts +18 -1
- package/dist/openApiSchema/references.core.js +21 -1
- package/dist/openApiSchema/schemaConverter.core.d.ts +51 -3
- package/dist/openApiSchema/schemaConverter.core.js +475 -118
- package/dist/openApiSchema/schemaRegistry.core.d.ts +27 -10
- package/dist/openApiSchema/schemaRegistry.core.js +33 -14
- package/dist/openApiSerialization/openApiSerializer.core.d.ts +10 -4
- package/dist/openApiSerialization/openApiSerializer.core.js +135 -9
- package/dist/openApiTypes/index.d.ts +1 -1
- package/dist/openApiTypes/openApiDocument.type.d.ts +16 -0
- package/dist/openApiTypes/openApiSchema.type.d.ts +24 -1
- package/dist/openApiTypes/openApiSchema.type.js +3 -0
- package/dist/openApiUi/index.d.ts +8 -0
- package/dist/openApiUi/index.js +8 -0
- package/dist/openApiUi/openApiUi.brand.d.ts +26 -0
- package/dist/openApiUi/openApiUi.brand.js +44 -0
- package/dist/openApiUi/openApiUi.core.d.ts +47 -0
- package/dist/openApiUi/openApiUi.core.js +143 -0
- package/dist/openApiValidation/index.d.ts +2 -2
- package/dist/openApiValidation/index.js +1 -1
- package/dist/openApiValidation/openApiValidator.core.d.ts +33 -11
- package/dist/openApiValidation/openApiValidator.core.js +274 -66
- package/package.json +25 -18
- package/dist/.tsbuildinfo +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/openApiComponents/index.d.ts.map +0 -1
- package/dist/openApiComponents/index.js.map +0 -1
- package/dist/openApiConstants/index.d.ts.map +0 -1
- package/dist/openApiConstants/index.js.map +0 -1
- package/dist/openApiConstants/openApiConstants.core.d.ts.map +0 -1
- package/dist/openApiConstants/openApiConstants.core.js.map +0 -1
- package/dist/openApiDocument/index.d.ts.map +0 -1
- package/dist/openApiDocument/index.js.map +0 -1
- package/dist/openApiDocument/openApiDocument.builder.d.ts.map +0 -1
- package/dist/openApiDocument/openApiDocument.builder.js.map +0 -1
- package/dist/openApiErrors/index.d.ts.map +0 -1
- package/dist/openApiErrors/index.js.map +0 -1
- package/dist/openApiErrors/openApiError.base.d.ts.map +0 -1
- package/dist/openApiErrors/openApiError.base.js.map +0 -1
- package/dist/openApiErrors/openApiError.core.d.ts.map +0 -1
- package/dist/openApiErrors/openApiError.core.js.map +0 -1
- package/dist/openApiErrors/openApiError.types.d.ts.map +0 -1
- package/dist/openApiErrors/openApiError.types.js.map +0 -1
- package/dist/openApiHttp/index.d.ts.map +0 -1
- package/dist/openApiHttp/index.js.map +0 -1
- package/dist/openApiHttp/openApiHttpAdapter.core.d.ts.map +0 -1
- package/dist/openApiHttp/openApiHttpAdapter.core.js.map +0 -1
- package/dist/openApiRegistry/index.d.ts.map +0 -1
- package/dist/openApiRegistry/index.js.map +0 -1
- package/dist/openApiRegistry/openApiRegistry.core.d.ts.map +0 -1
- package/dist/openApiRegistry/openApiRegistry.core.js.map +0 -1
- package/dist/openApiRegistry/openApiRegistry.type.d.ts.map +0 -1
- package/dist/openApiRegistry/openApiRegistry.type.js.map +0 -1
- package/dist/openApiRouting/index.d.ts.map +0 -1
- package/dist/openApiRouting/index.js.map +0 -1
- package/dist/openApiRouting/routeConverter.core.d.ts.map +0 -1
- package/dist/openApiRouting/routeConverter.core.js.map +0 -1
- package/dist/openApiRouting/routeMetadata.type.d.ts.map +0 -1
- package/dist/openApiRouting/routeMetadata.type.js.map +0 -1
- package/dist/openApiRouting/routeScanner.core.d.ts.map +0 -1
- package/dist/openApiRouting/routeScanner.core.js.map +0 -1
- package/dist/openApiSchema/index.d.ts.map +0 -1
- package/dist/openApiSchema/index.js.map +0 -1
- package/dist/openApiSchema/references.core.d.ts.map +0 -1
- package/dist/openApiSchema/references.core.js.map +0 -1
- package/dist/openApiSchema/schemaConverter.core.d.ts.map +0 -1
- package/dist/openApiSchema/schemaConverter.core.js.map +0 -1
- package/dist/openApiSchema/schemaRegistry.core.d.ts.map +0 -1
- package/dist/openApiSchema/schemaRegistry.core.js.map +0 -1
- package/dist/openApiSerialization/index.d.ts.map +0 -1
- package/dist/openApiSerialization/index.js.map +0 -1
- package/dist/openApiSerialization/openApiSerializer.core.d.ts.map +0 -1
- package/dist/openApiSerialization/openApiSerializer.core.js.map +0 -1
- package/dist/openApiTypes/index.d.ts.map +0 -1
- package/dist/openApiTypes/index.js.map +0 -1
- package/dist/openApiTypes/openApiComponent.type.d.ts.map +0 -1
- package/dist/openApiTypes/openApiComponent.type.js.map +0 -1
- package/dist/openApiTypes/openApiDocument.type.d.ts.map +0 -1
- package/dist/openApiTypes/openApiDocument.type.js.map +0 -1
- package/dist/openApiTypes/openApiPath.type.d.ts.map +0 -1
- package/dist/openApiTypes/openApiPath.type.js.map +0 -1
- package/dist/openApiTypes/openApiSchema.type.d.ts.map +0 -1
- package/dist/openApiTypes/openApiSchema.type.js.map +0 -1
- package/dist/openApiTypes/openApiSecurity.type.d.ts.map +0 -1
- package/dist/openApiTypes/openApiSecurity.type.js.map +0 -1
- package/dist/openApiTypes/openApiTypes.core.d.ts.map +0 -1
- package/dist/openApiTypes/openApiTypes.core.js.map +0 -1
- package/dist/openApiValidation/index.d.ts.map +0 -1
- package/dist/openApiValidation/index.js.map +0 -1
- package/dist/openApiValidation/openApiValidator.core.d.ts.map +0 -1
- package/dist/openApiValidation/openApiValidator.core.js.map +0 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { OpenAPIDocument, OpenAPIParameter, OpenAPIRequestBody, OpenAPISchema, OpenAPISecurityScheme, OpenAPITag, OpenAPIReference } from "../openApiTypes/openApiTypes.core.js";
|
|
1
|
+
import type { OpenAPIDocument, OpenAPIExample, OpenAPIHeader, OpenAPIInfo, OpenAPILink, OpenAPIParameter, OpenAPIPathItem, OpenAPIRequestBody, OpenAPIResponse, OpenAPISchema, OpenAPISecurityRequirement, OpenAPISecurityScheme, OpenAPIServer, OpenAPITag, OpenAPIReference } from "../openApiTypes/openApiTypes.core.js";
|
|
2
2
|
import type { OpenAPIRoute, OpenAPIRegistry } from "./openApiRegistry.type.js";
|
|
3
|
+
import type { ComponentSection } from "../openApiSchema/references.core.js";
|
|
3
4
|
/** Default OpenAPI registry implementation. */
|
|
4
5
|
export declare class OpenAPIRegistryImpl implements OpenAPIRegistry {
|
|
5
6
|
readonly version: string;
|
|
7
|
+
private info;
|
|
8
|
+
private readonly servers;
|
|
9
|
+
private readonly security;
|
|
6
10
|
private readonly routes;
|
|
7
11
|
private readonly schemas;
|
|
8
12
|
private readonly responses;
|
|
@@ -15,16 +19,45 @@ export declare class OpenAPIRegistryImpl implements OpenAPIRegistry {
|
|
|
15
19
|
private readonly links;
|
|
16
20
|
private readonly callbacks;
|
|
17
21
|
constructor(version?: string);
|
|
22
|
+
/** Sets the document's `info` object. */
|
|
23
|
+
setInfo(info: OpenAPIInfo): void;
|
|
24
|
+
/** The document's current `info` object. */
|
|
25
|
+
getInfo(): OpenAPIInfo;
|
|
26
|
+
addServer(server: OpenAPIServer): void;
|
|
27
|
+
addSecurityRequirement(requirement: OpenAPISecurityRequirement): void;
|
|
28
|
+
private static routeKey;
|
|
18
29
|
registerRoute(route: OpenAPIRoute): void;
|
|
30
|
+
/**
|
|
31
|
+
* Registers a route, replacing any existing one.
|
|
32
|
+
*
|
|
33
|
+
* This is what makes regeneration idempotent: re-registering the same routes
|
|
34
|
+
* into a registry that already holds them used to throw, so calling
|
|
35
|
+
* `generate()` twice failed.
|
|
36
|
+
*/
|
|
37
|
+
setRoute(route: OpenAPIRoute): void;
|
|
38
|
+
private static register;
|
|
19
39
|
registerSchema(name: string, schema: OpenAPISchema): void;
|
|
20
|
-
registerResponse(name: string, response:
|
|
40
|
+
registerResponse(name: string, response: OpenAPIResponse): void;
|
|
21
41
|
registerParameter(name: string, parameter: OpenAPIParameter): void;
|
|
22
42
|
registerRequestBody(name: string, body: OpenAPIRequestBody): void;
|
|
23
|
-
registerHeader(name: string, header:
|
|
24
|
-
registerExample(name: string, example:
|
|
43
|
+
registerHeader(name: string, header: OpenAPIHeader): void;
|
|
44
|
+
registerExample(name: string, example: OpenAPIExample): void;
|
|
25
45
|
registerSecurityScheme(name: string, scheme: OpenAPISecurityScheme): void;
|
|
46
|
+
registerLink(name: string, link: OpenAPILink): void;
|
|
47
|
+
registerCallback(name: string, callback: Readonly<Record<string, OpenAPIPathItem>>): void;
|
|
48
|
+
/**
|
|
49
|
+
* Registers a tag.
|
|
50
|
+
*
|
|
51
|
+
* Re-registering a tag name conflicts, like every other component: quietly
|
|
52
|
+
* keeping the first definition discarded corrected descriptions without a
|
|
53
|
+
* word.
|
|
54
|
+
*/
|
|
26
55
|
registerTag(tag: OpenAPITag): void;
|
|
27
|
-
|
|
56
|
+
/** Registers a tag, replacing any existing one with the same name. */
|
|
57
|
+
setTag(tag: OpenAPITag): void;
|
|
58
|
+
ref(section: ComponentSection, name: string): OpenAPIReference;
|
|
59
|
+
hasComponent(section: ComponentSection, name: string): boolean;
|
|
60
|
+
private componentMap;
|
|
28
61
|
generate(): OpenAPIDocument;
|
|
29
62
|
clear(): void;
|
|
30
63
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createComponentReference } from "../openApiSchema/references.core.js";
|
|
2
|
+
import { DEFAULT_OPENAPI_VERSION, SUPPORTED_OPENAPI_VERSIONS, } from "../openApiConstants/openApiConstants.core.js";
|
|
3
|
+
import { OpenAPIComponentConflictError, OpenAPIOperationError, OpenAPIVersionError, } from "../openApiErrors/openApiError.types.js";
|
|
4
|
+
/** Placeholder used until {@link OpenAPIRegistryImpl.setInfo} is called. */
|
|
5
|
+
const DEFAULT_INFO = { title: "API", version: "0.0.0" };
|
|
3
6
|
/** Default OpenAPI registry implementation. */
|
|
4
7
|
export class OpenAPIRegistryImpl {
|
|
5
8
|
version;
|
|
9
|
+
info = DEFAULT_INFO;
|
|
10
|
+
servers = [];
|
|
11
|
+
security = [];
|
|
6
12
|
routes = new Map();
|
|
7
13
|
schemas = new Map();
|
|
8
14
|
responses = new Map();
|
|
@@ -15,14 +21,55 @@ export class OpenAPIRegistryImpl {
|
|
|
15
21
|
links = new Map();
|
|
16
22
|
callbacks = new Map();
|
|
17
23
|
constructor(version = DEFAULT_OPENAPI_VERSION) {
|
|
24
|
+
if (!SUPPORTED_OPENAPI_VERSIONS.includes(version)) {
|
|
25
|
+
// Fail where the version is chosen, not later inside generate().
|
|
26
|
+
throw new OpenAPIVersionError(version, SUPPORTED_OPENAPI_VERSIONS);
|
|
27
|
+
}
|
|
18
28
|
this.version = version;
|
|
19
29
|
}
|
|
30
|
+
/** Sets the document's `info` object. */
|
|
31
|
+
setInfo(info) {
|
|
32
|
+
this.info = { ...info };
|
|
33
|
+
}
|
|
34
|
+
/** The document's current `info` object. */
|
|
35
|
+
getInfo() {
|
|
36
|
+
return { ...this.info };
|
|
37
|
+
}
|
|
38
|
+
addServer(server) {
|
|
39
|
+
this.servers.push({ ...server });
|
|
40
|
+
}
|
|
41
|
+
addSecurityRequirement(requirement) {
|
|
42
|
+
this.security.push({ ...requirement });
|
|
43
|
+
}
|
|
44
|
+
static routeKey(route) {
|
|
45
|
+
return `${route.method.toLowerCase()}:${route.path}`;
|
|
46
|
+
}
|
|
20
47
|
registerRoute(route) {
|
|
21
|
-
const key =
|
|
48
|
+
const key = OpenAPIRegistryImpl.routeKey(route);
|
|
22
49
|
const existing = this.routes.get(key);
|
|
23
|
-
if (existing)
|
|
24
|
-
throw new OpenAPIOperationError(`Duplicate operation for ${route.method.toUpperCase()} ${route.path}
|
|
25
|
-
|
|
50
|
+
if (existing) {
|
|
51
|
+
throw new OpenAPIOperationError(`Duplicate operation for ${route.method.toUpperCase()} ${route.path}` +
|
|
52
|
+
(existing.operation.operationId
|
|
53
|
+
? ` (already registered as "${existing.operation.operationId}")`
|
|
54
|
+
: ""), {
|
|
55
|
+
metadata: {
|
|
56
|
+
method: route.method,
|
|
57
|
+
path: route.path,
|
|
58
|
+
operationId: existing.operation.operationId,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
this.setRoute(route);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Registers a route, replacing any existing one.
|
|
66
|
+
*
|
|
67
|
+
* This is what makes regeneration idempotent: re-registering the same routes
|
|
68
|
+
* into a registry that already holds them used to throw, so calling
|
|
69
|
+
* `generate()` twice failed.
|
|
70
|
+
*/
|
|
71
|
+
setRoute(route) {
|
|
72
|
+
this.routes.set(OpenAPIRegistryImpl.routeKey(route), {
|
|
26
73
|
...route,
|
|
27
74
|
operation: Object.freeze({
|
|
28
75
|
...route.operation,
|
|
@@ -30,72 +77,121 @@ export class OpenAPIRegistryImpl {
|
|
|
30
77
|
}),
|
|
31
78
|
});
|
|
32
79
|
}
|
|
80
|
+
static register(map, section, name, value) {
|
|
81
|
+
if (map.has(name)) {
|
|
82
|
+
throw new OpenAPIComponentConflictError(section, name);
|
|
83
|
+
}
|
|
84
|
+
map.set(name, Object.freeze(value));
|
|
85
|
+
}
|
|
33
86
|
registerSchema(name, schema) {
|
|
34
|
-
|
|
35
|
-
throw new OpenAPIComponentConflictError(`schemas/${name}`);
|
|
36
|
-
this.schemas.set(name, Object.freeze({ ...schema }));
|
|
87
|
+
OpenAPIRegistryImpl.register(this.schemas, "schemas", name, { ...schema });
|
|
37
88
|
}
|
|
38
89
|
registerResponse(name, response) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
90
|
+
OpenAPIRegistryImpl.register(this.responses, "responses", name, {
|
|
91
|
+
...response,
|
|
92
|
+
});
|
|
42
93
|
}
|
|
43
94
|
registerParameter(name, parameter) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
95
|
+
OpenAPIRegistryImpl.register(this.parameters, "parameters", name, {
|
|
96
|
+
...parameter,
|
|
97
|
+
});
|
|
47
98
|
}
|
|
48
99
|
registerRequestBody(name, body) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
100
|
+
OpenAPIRegistryImpl.register(this.requestBodies, "requestBodies", name, {
|
|
101
|
+
...body,
|
|
102
|
+
});
|
|
52
103
|
}
|
|
53
104
|
registerHeader(name, header) {
|
|
54
|
-
|
|
55
|
-
throw new OpenAPIComponentConflictError(`headers/${name}`);
|
|
56
|
-
this.headers.set(name, Object.freeze({ ...header }));
|
|
105
|
+
OpenAPIRegistryImpl.register(this.headers, "headers", name, { ...header });
|
|
57
106
|
}
|
|
58
107
|
registerExample(name, example) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
108
|
+
OpenAPIRegistryImpl.register(this.examples, "examples", name, {
|
|
109
|
+
...example,
|
|
110
|
+
});
|
|
62
111
|
}
|
|
63
112
|
registerSecurityScheme(name, scheme) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
113
|
+
OpenAPIRegistryImpl.register(this.securitySchemes, "securitySchemes", name, {
|
|
114
|
+
...scheme,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
registerLink(name, link) {
|
|
118
|
+
OpenAPIRegistryImpl.register(this.links, "links", name, { ...link });
|
|
119
|
+
}
|
|
120
|
+
registerCallback(name, callback) {
|
|
121
|
+
OpenAPIRegistryImpl.register(this.callbacks, "callbacks", name, {
|
|
122
|
+
...callback,
|
|
123
|
+
});
|
|
67
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Registers a tag.
|
|
127
|
+
*
|
|
128
|
+
* Re-registering a tag name conflicts, like every other component: quietly
|
|
129
|
+
* keeping the first definition discarded corrected descriptions without a
|
|
130
|
+
* word.
|
|
131
|
+
*/
|
|
68
132
|
registerTag(tag) {
|
|
69
|
-
if (
|
|
70
|
-
|
|
133
|
+
if (this.tags.has(tag.name)) {
|
|
134
|
+
throw new OpenAPIComponentConflictError("tags", tag.name);
|
|
135
|
+
}
|
|
136
|
+
this.tags.set(tag.name, Object.freeze({ ...tag }));
|
|
137
|
+
}
|
|
138
|
+
/** Registers a tag, replacing any existing one with the same name. */
|
|
139
|
+
setTag(tag) {
|
|
140
|
+
this.tags.set(tag.name, Object.freeze({ ...tag }));
|
|
71
141
|
}
|
|
72
142
|
ref(section, name) {
|
|
73
|
-
return
|
|
143
|
+
return createComponentReference(section, name);
|
|
144
|
+
}
|
|
145
|
+
hasComponent(section, name) {
|
|
146
|
+
return this.componentMap(section)?.has(name) ?? false;
|
|
147
|
+
}
|
|
148
|
+
componentMap(section) {
|
|
149
|
+
switch (section) {
|
|
150
|
+
case "schemas":
|
|
151
|
+
return this.schemas;
|
|
152
|
+
case "responses":
|
|
153
|
+
return this.responses;
|
|
154
|
+
case "parameters":
|
|
155
|
+
return this.parameters;
|
|
156
|
+
case "requestBodies":
|
|
157
|
+
return this.requestBodies;
|
|
158
|
+
case "headers":
|
|
159
|
+
return this.headers;
|
|
160
|
+
case "examples":
|
|
161
|
+
return this.examples;
|
|
162
|
+
case "securitySchemes":
|
|
163
|
+
return this.securitySchemes;
|
|
164
|
+
case "links":
|
|
165
|
+
return this.links;
|
|
166
|
+
case "callbacks":
|
|
167
|
+
return this.callbacks;
|
|
168
|
+
default:
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
74
171
|
}
|
|
75
172
|
generate() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
173
|
+
// A `Map` rather than an object literal: a route registered at the path
|
|
174
|
+
// `__proto__` assigned to a literal sets the object's prototype instead
|
|
175
|
+
// of adding an entry, so the path disappears from the document with no
|
|
176
|
+
// error raised anywhere. `Object.fromEntries` defines own properties and
|
|
177
|
+
// has no such hole.
|
|
178
|
+
const paths = new Map();
|
|
179
|
+
for (const route of this.routes.values()) {
|
|
80
180
|
const operation = Object.freeze({
|
|
81
181
|
...route.operation,
|
|
82
182
|
responses: Object.freeze({ ...route.operation.responses }),
|
|
83
183
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
...(route.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
...(route.operation.parameters?.length
|
|
96
|
-
? { parameters: Object.freeze([...route.operation.parameters]) }
|
|
97
|
-
: {}),
|
|
98
|
-
});
|
|
184
|
+
// Operations keep their own parameters. Hoisting them to the path item
|
|
185
|
+
// makes them apply to every method on that path, so two methods with
|
|
186
|
+
// different parameters overwrote one another.
|
|
187
|
+
//
|
|
188
|
+
// The method is lower-cased here as well as in the cache key: a path
|
|
189
|
+
// item field is defined in lower case, and `GET` would emit a field no
|
|
190
|
+
// consumer recognises while still colliding on the key.
|
|
191
|
+
paths.set(route.path, Object.freeze({
|
|
192
|
+
...(paths.get(route.path) ?? {}),
|
|
193
|
+
[route.method.toLowerCase()]: operation,
|
|
194
|
+
}));
|
|
99
195
|
}
|
|
100
196
|
const components = {};
|
|
101
197
|
const componentMaps = [
|
|
@@ -113,24 +209,28 @@ export class OpenAPIRegistryImpl {
|
|
|
113
209
|
if (map.size > 0)
|
|
114
210
|
components[key] = Object.freeze(Object.fromEntries(map));
|
|
115
211
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
212
|
+
return Object.freeze({
|
|
213
|
+
openapi: this.version,
|
|
214
|
+
info: Object.freeze({ ...this.info }),
|
|
215
|
+
...(this.servers.length > 0
|
|
216
|
+
? { servers: Object.freeze([...this.servers]) }
|
|
217
|
+
: {}),
|
|
218
|
+
paths: Object.freeze(Object.fromEntries(paths)),
|
|
219
|
+
...(Object.keys(components).length > 0
|
|
220
|
+
? { components: Object.freeze(components) }
|
|
221
|
+
: {}),
|
|
222
|
+
...(this.security.length > 0
|
|
223
|
+
? { security: Object.freeze([...this.security]) }
|
|
224
|
+
: {}),
|
|
225
|
+
...(this.tags.size > 0
|
|
226
|
+
? { tags: Object.freeze([...this.tags.values()]) }
|
|
227
|
+
: {}),
|
|
228
|
+
});
|
|
132
229
|
}
|
|
133
230
|
clear() {
|
|
231
|
+
this.info = DEFAULT_INFO;
|
|
232
|
+
this.servers.length = 0;
|
|
233
|
+
this.security.length = 0;
|
|
134
234
|
for (const map of [
|
|
135
235
|
this.routes,
|
|
136
236
|
this.schemas,
|
|
@@ -143,8 +243,9 @@ export class OpenAPIRegistryImpl {
|
|
|
143
243
|
this.tags,
|
|
144
244
|
this.links,
|
|
145
245
|
this.callbacks,
|
|
146
|
-
])
|
|
246
|
+
]) {
|
|
147
247
|
map.clear();
|
|
248
|
+
}
|
|
148
249
|
}
|
|
149
250
|
}
|
|
150
251
|
//# sourceMappingURL=openApiRegistry.core.js.map
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import type { OpenAPIDocument } from "../openApiTypes/openApiTypes.core.js";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { OpenAPIRequestBody } from "../openApiTypes/openApiTypes.core.js";
|
|
5
|
-
import type { OpenAPISchema } from "../openApiTypes/openApiTypes.core.js";
|
|
6
|
-
import type { OpenAPISecurityScheme } from "../openApiTypes/openApiTypes.core.js";
|
|
7
|
-
import type { OpenAPITag } from "../openApiTypes/openApiTypes.core.js";
|
|
8
|
-
import type { OpenAPIReference } from "../openApiTypes/openApiTypes.core.js";
|
|
1
|
+
import type { OpenAPIDocument, OpenAPIInfo, OpenAPIOperation, OpenAPIParameter, OpenAPIRequestBody, OpenAPIResponse, OpenAPISchema, OpenAPISecurityRequirement, OpenAPISecurityScheme, OpenAPIServer, OpenAPITag, OpenAPIReference, OpenAPIHeader, OpenAPIExample, OpenAPILink, OpenAPIPathItem } from "../openApiTypes/openApiTypes.core.js";
|
|
2
|
+
import type { OpenAPIHttpMethod } from "../openApiRouting/routeMetadata.type.js";
|
|
3
|
+
import type { ComponentSection } from "../openApiSchema/references.core.js";
|
|
9
4
|
/**
|
|
10
5
|
* A registered route in the OpenAPI registry.
|
|
11
6
|
*/
|
|
12
7
|
export interface OpenAPIRoute {
|
|
13
|
-
readonly method:
|
|
8
|
+
readonly method: OpenAPIHttpMethod;
|
|
14
9
|
readonly path: string;
|
|
15
10
|
readonly operation: OpenAPIOperation;
|
|
16
11
|
}
|
|
@@ -26,16 +21,26 @@ export interface OpenAPIComponentRegistration<T> {
|
|
|
26
21
|
*/
|
|
27
22
|
export interface OpenAPIRegistry {
|
|
28
23
|
readonly version: string;
|
|
24
|
+
/** Document-level metadata. Defaults to a placeholder title and version. */
|
|
25
|
+
setInfo(info: OpenAPIInfo): void;
|
|
26
|
+
addServer(server: OpenAPIServer): void;
|
|
27
|
+
addSecurityRequirement(requirement: OpenAPISecurityRequirement): void;
|
|
29
28
|
registerRoute(route: OpenAPIRoute): void;
|
|
29
|
+
/** Registers a route, replacing any existing one for the same method+path. */
|
|
30
|
+
setRoute(route: OpenAPIRoute): void;
|
|
30
31
|
registerSchema(name: string, schema: OpenAPISchema): void;
|
|
31
|
-
registerResponse(name: string, response:
|
|
32
|
+
registerResponse(name: string, response: OpenAPIResponse): void;
|
|
32
33
|
registerParameter(name: string, parameter: OpenAPIParameter): void;
|
|
33
34
|
registerRequestBody(name: string, body: OpenAPIRequestBody): void;
|
|
34
|
-
registerHeader(name: string, header:
|
|
35
|
-
registerExample(name: string, example:
|
|
35
|
+
registerHeader(name: string, header: OpenAPIHeader): void;
|
|
36
|
+
registerExample(name: string, example: OpenAPIExample): void;
|
|
36
37
|
registerSecurityScheme(name: string, scheme: OpenAPISecurityScheme): void;
|
|
38
|
+
registerLink(name: string, link: OpenAPILink): void;
|
|
39
|
+
registerCallback(name: string, callback: Readonly<Record<string, OpenAPIPathItem>>): void;
|
|
37
40
|
registerTag(tag: OpenAPITag): void;
|
|
38
|
-
ref(section:
|
|
41
|
+
ref(section: ComponentSection, name: string): OpenAPIReference;
|
|
42
|
+
/** True when a component is registered under that section and name. */
|
|
43
|
+
hasComponent(section: ComponentSection, name: string): boolean;
|
|
39
44
|
generate(): OpenAPIDocument;
|
|
40
45
|
clear(): void;
|
|
41
46
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { OpenAPIComponentConflictError, OpenAPIDocumentError, OpenAPIOperationError, } from "../openApiErrors/openApiError.core.js";
|
|
1
|
+
export {};
|
|
3
2
|
//# sourceMappingURL=openApiRegistry.type.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Route metadata, conversion, and scanning for OpenAPI generation.
|
|
5
5
|
*/
|
|
6
|
-
export type { RouteMetadata, RouteOpenAPIMetadata, RouteParameterMetadata, RouteInfo, } from "./
|
|
7
|
-
export { toOpenAPIPath, convertRouteToOpenAPI, ZUDOLIB_TO_OPENAPI_METHODS, } from "./routeConverter.core.js";
|
|
6
|
+
export type { RouteMetadata, RouteOpenAPIMetadata, RouteParameterMetadata, RouteInfo, OpenAPIHttpMethod, } from "./routeMetadata.type.js";
|
|
7
|
+
export { toOpenAPIPath, extractPathParameters, convertRouteToOpenAPI, buildResponses, isOpenAPIMethod, ZUDOLIB_TO_OPENAPI_METHODS, } from "./routeConverter.core.js";
|
|
8
8
|
export { OpenAPIRouteScannerImpl } from "./routeScanner.core.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Route metadata, conversion, and scanning for OpenAPI generation.
|
|
5
5
|
*/
|
|
6
|
-
export { toOpenAPIPath, convertRouteToOpenAPI, ZUDOLIB_TO_OPENAPI_METHODS, } from "./routeConverter.core.js";
|
|
6
|
+
export { toOpenAPIPath, extractPathParameters, convertRouteToOpenAPI, buildResponses, isOpenAPIMethod, ZUDOLIB_TO_OPENAPI_METHODS, } from "./routeConverter.core.js";
|
|
7
7
|
export { OpenAPIRouteScannerImpl } from "./routeScanner.core.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,22 +1,40 @@
|
|
|
1
|
-
import type { OpenAPIOperation } from "../openApiTypes/openApiTypes.core.js";
|
|
2
|
-
import type { RouteMetadata } from "./routeMetadata.type.js";
|
|
1
|
+
import type { OpenAPIOperation, OpenAPIResponses } from "../openApiTypes/openApiTypes.core.js";
|
|
2
|
+
import type { OpenAPIHttpMethod, RouteMetadata } from "./routeMetadata.type.js";
|
|
3
|
+
/**
|
|
4
|
+
* Maps Zudojs HTTP methods to OpenAPI methods.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ZUDOLIB_TO_OPENAPI_METHODS: readonly ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
7
|
+
/** True when `method` is one an OpenAPI path item can carry. */
|
|
8
|
+
export declare function isOpenAPIMethod(method: string): method is OpenAPIHttpMethod;
|
|
3
9
|
/**
|
|
4
10
|
* Converts a Zudojs-style route path to an OpenAPI path template.
|
|
5
11
|
*
|
|
6
12
|
* Example:
|
|
7
|
-
*
|
|
8
|
-
*
|
|
13
|
+
* `/users/:id` → `/users/{id}`
|
|
14
|
+
* `/users/{id}` → unchanged (already a template)
|
|
15
|
+
* `/users/:id?` → throws (OpenAPI has no optional path parameters)
|
|
16
|
+
* `/files/*` → throws (OpenAPI has no wildcard paths)
|
|
17
|
+
*
|
|
18
|
+
* Anything it cannot convert throws rather than passing through: an
|
|
19
|
+
* unconvertible segment that reaches the document produces an invalid path
|
|
20
|
+
* template, and the failure then surfaces in whatever consumes the spec
|
|
21
|
+
* rather than at the route that caused it.
|
|
9
22
|
*/
|
|
10
23
|
export declare function toOpenAPIPath(path: string): string;
|
|
24
|
+
/** Extracts the parameter names from an OpenAPI path template. */
|
|
25
|
+
export declare function extractPathParameters(path: string): readonly string[];
|
|
11
26
|
/**
|
|
12
|
-
*
|
|
27
|
+
* Builds the `responses` object for an operation.
|
|
28
|
+
*
|
|
29
|
+
* Every documented response is carried through. Only when a route documents
|
|
30
|
+
* none at all is a `200` synthesized, because `responses` is required.
|
|
13
31
|
*/
|
|
14
|
-
export declare
|
|
32
|
+
export declare function buildResponses(metadata?: RouteMetadata): OpenAPIResponses;
|
|
15
33
|
/**
|
|
16
34
|
* Converts a route with metadata into an OpenAPI operation.
|
|
17
35
|
*/
|
|
18
36
|
export declare function convertRouteToOpenAPI(method: string, path: string, metadata?: RouteMetadata): {
|
|
19
|
-
method:
|
|
37
|
+
method: OpenAPIHttpMethod;
|
|
20
38
|
path: string;
|
|
21
39
|
operation: OpenAPIOperation;
|
|
22
40
|
};
|