@riktajs/swagger 0.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/README.md +258 -0
- package/dist/constants.d.ts +56 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +61 -0
- package/dist/constants.js.map +1 -0
- package/dist/decorators/api-body.decorator.d.ts +33 -0
- package/dist/decorators/api-body.decorator.d.ts.map +1 -0
- package/dist/decorators/api-body.decorator.js +40 -0
- package/dist/decorators/api-body.decorator.js.map +1 -0
- package/dist/decorators/api-exclude.decorator.d.ts +71 -0
- package/dist/decorators/api-exclude.decorator.d.ts.map +1 -0
- package/dist/decorators/api-exclude.decorator.js +95 -0
- package/dist/decorators/api-exclude.decorator.js.map +1 -0
- package/dist/decorators/api-header.decorator.d.ts +25 -0
- package/dist/decorators/api-header.decorator.d.ts.map +1 -0
- package/dist/decorators/api-header.decorator.js +33 -0
- package/dist/decorators/api-header.decorator.js.map +1 -0
- package/dist/decorators/api-operation.decorator.d.ts +32 -0
- package/dist/decorators/api-operation.decorator.d.ts.map +1 -0
- package/dist/decorators/api-operation.decorator.js +39 -0
- package/dist/decorators/api-operation.decorator.js.map +1 -0
- package/dist/decorators/api-param.decorator.d.ts +28 -0
- package/dist/decorators/api-param.decorator.d.ts.map +1 -0
- package/dist/decorators/api-param.decorator.js +36 -0
- package/dist/decorators/api-param.decorator.js.map +1 -0
- package/dist/decorators/api-property.decorator.d.ts +69 -0
- package/dist/decorators/api-property.decorator.d.ts.map +1 -0
- package/dist/decorators/api-property.decorator.js +76 -0
- package/dist/decorators/api-property.decorator.js.map +1 -0
- package/dist/decorators/api-query.decorator.d.ts +30 -0
- package/dist/decorators/api-query.decorator.d.ts.map +1 -0
- package/dist/decorators/api-query.decorator.js +38 -0
- package/dist/decorators/api-query.decorator.js.map +1 -0
- package/dist/decorators/api-response.decorator.d.ts +70 -0
- package/dist/decorators/api-response.decorator.d.ts.map +1 -0
- package/dist/decorators/api-response.decorator.js +100 -0
- package/dist/decorators/api-response.decorator.js.map +1 -0
- package/dist/decorators/api-security.decorator.d.ts +88 -0
- package/dist/decorators/api-security.decorator.d.ts.map +1 -0
- package/dist/decorators/api-security.decorator.js +119 -0
- package/dist/decorators/api-security.decorator.js.map +1 -0
- package/dist/decorators/api-tags.decorator.d.ts +31 -0
- package/dist/decorators/api-tags.decorator.d.ts.map +1 -0
- package/dist/decorators/api-tags.decorator.js +52 -0
- package/dist/decorators/api-tags.decorator.js.map +1 -0
- package/dist/decorators/index.d.ts +16 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +24 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi/generator.d.ts +98 -0
- package/dist/openapi/generator.d.ts.map +1 -0
- package/dist/openapi/generator.js +493 -0
- package/dist/openapi/generator.js.map +1 -0
- package/dist/openapi/index.d.ts +8 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +11 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi/zod-to-openapi.d.ts +52 -0
- package/dist/openapi/zod-to-openapi.d.ts.map +1 -0
- package/dist/openapi/zod-to-openapi.js +172 -0
- package/dist/openapi/zod-to-openapi.js.map +1 -0
- package/dist/plugin/index.d.ts +7 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +7 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/swagger.plugin.d.ts +157 -0
- package/dist/plugin/swagger.plugin.d.ts.map +1 -0
- package/dist/plugin/swagger.plugin.js +235 -0
- package/dist/plugin/swagger.plugin.js.map +1 -0
- package/dist/types.d.ts +511 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { ParamType,
|
|
3
|
+
// Metadata helper functions
|
|
4
|
+
getControllerMetadata, getRoutes, getParamMetadata as getCoreParamMetadata, getHttpCode, getClassMetadata, getMethodMetadata, } from '@riktajs/core';
|
|
5
|
+
import { API_TAGS_METADATA, API_OPERATION_METADATA, API_RESPONSE_METADATA, API_BODY_METADATA, API_PARAM_METADATA, API_QUERY_METADATA, API_HEADER_METADATA, API_SECURITY_METADATA, API_EXCLUDE_METADATA, API_DEPRECATED_METADATA, } from '../constants.js';
|
|
6
|
+
import { zodToOpenApi, toOpenApiSchema } from './zod-to-openapi.js';
|
|
7
|
+
/**
|
|
8
|
+
* Default swagger config values
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_SWAGGER_CONFIG = {
|
|
11
|
+
info: {
|
|
12
|
+
title: 'API Documentation',
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* OpenAPI Specification Generator
|
|
18
|
+
*
|
|
19
|
+
* Collects metadata from controllers and generates a complete
|
|
20
|
+
* OpenAPI 3.0.3 specification document.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const generator = new OpenApiGenerator({
|
|
25
|
+
* info: {
|
|
26
|
+
* title: 'My API',
|
|
27
|
+
* version: '1.0.0',
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Add controllers to scan
|
|
32
|
+
* generator.addController(UserController);
|
|
33
|
+
* generator.addController(ProductController);
|
|
34
|
+
*
|
|
35
|
+
* // Generate the specification
|
|
36
|
+
* const spec = generator.generate();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class OpenApiGenerator {
|
|
40
|
+
config;
|
|
41
|
+
controllers = [];
|
|
42
|
+
globalSecuritySchemes = new Map();
|
|
43
|
+
constructor(config = {}) {
|
|
44
|
+
// Build info object from shorthand or full info
|
|
45
|
+
const info = config.info ?? {
|
|
46
|
+
title: config.title ?? DEFAULT_SWAGGER_CONFIG.info?.title ?? 'API Documentation',
|
|
47
|
+
version: config.version ?? DEFAULT_SWAGGER_CONFIG.info?.version ?? '1.0.0',
|
|
48
|
+
description: config.description,
|
|
49
|
+
contact: config.contact,
|
|
50
|
+
license: config.license,
|
|
51
|
+
termsOfService: config.termsOfService,
|
|
52
|
+
};
|
|
53
|
+
// Extract remaining config (excluding shorthand properties)
|
|
54
|
+
const { title, version, description, contact, license, termsOfService, ...restConfig } = config;
|
|
55
|
+
this.config = {
|
|
56
|
+
...DEFAULT_SWAGGER_CONFIG,
|
|
57
|
+
...restConfig,
|
|
58
|
+
info,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Add a controller to be documented
|
|
63
|
+
*/
|
|
64
|
+
addController(controller) {
|
|
65
|
+
this.controllers.push(controller);
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add multiple controllers
|
|
70
|
+
*/
|
|
71
|
+
addControllers(controllers) {
|
|
72
|
+
this.controllers.push(...controllers);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add a global security scheme
|
|
77
|
+
*/
|
|
78
|
+
addSecurityScheme(name, scheme) {
|
|
79
|
+
this.globalSecuritySchemes.set(name, scheme);
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Generate the OpenAPI specification document
|
|
84
|
+
*/
|
|
85
|
+
generate() {
|
|
86
|
+
const paths = {};
|
|
87
|
+
const tags = [];
|
|
88
|
+
const seenTags = new Set();
|
|
89
|
+
for (const controller of this.controllers) {
|
|
90
|
+
// Check if controller is excluded
|
|
91
|
+
if (this.isControllerExcluded(controller)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const controllerMeta = this.getControllerMeta(controller);
|
|
95
|
+
if (!controllerMeta)
|
|
96
|
+
continue;
|
|
97
|
+
const controllerTags = this.getControllerTags(controller);
|
|
98
|
+
const controllerDeprecated = this.isControllerDeprecated(controller);
|
|
99
|
+
// Add controller tags to the global tags list
|
|
100
|
+
for (const tag of controllerTags) {
|
|
101
|
+
if (!seenTags.has(tag)) {
|
|
102
|
+
seenTags.add(tag);
|
|
103
|
+
tags.push({ name: tag });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Process each route
|
|
107
|
+
const routes = this.getControllerRoutes(controller);
|
|
108
|
+
for (const route of routes) {
|
|
109
|
+
// Check if endpoint is excluded
|
|
110
|
+
if (this.isEndpointExcluded(controller, route.handlerName)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const fullPath = this.normalizePath(controllerMeta.prefix, route.path);
|
|
114
|
+
const method = route.method.toLowerCase();
|
|
115
|
+
if (!paths[fullPath]) {
|
|
116
|
+
paths[fullPath] = {};
|
|
117
|
+
}
|
|
118
|
+
const operation = this.buildOperation(controller, route, controllerTags, controllerDeprecated);
|
|
119
|
+
// Assign operation to the path item using method as key
|
|
120
|
+
paths[fullPath][method] = operation;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Build security schemes from global and controller-level definitions
|
|
124
|
+
const securitySchemes = this.buildSecuritySchemes();
|
|
125
|
+
const document = {
|
|
126
|
+
openapi: '3.0.3',
|
|
127
|
+
info: this.config.info,
|
|
128
|
+
paths,
|
|
129
|
+
};
|
|
130
|
+
if (tags.length > 0) {
|
|
131
|
+
document.tags = tags;
|
|
132
|
+
}
|
|
133
|
+
if (this.config.servers && this.config.servers.length > 0) {
|
|
134
|
+
document.servers = this.config.servers;
|
|
135
|
+
}
|
|
136
|
+
if (Object.keys(securitySchemes).length > 0) {
|
|
137
|
+
document.components = {
|
|
138
|
+
...document.components,
|
|
139
|
+
securitySchemes,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (this.config.externalDocs) {
|
|
143
|
+
document.externalDocs = this.config.externalDocs;
|
|
144
|
+
}
|
|
145
|
+
return document;
|
|
146
|
+
}
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Private: Metadata Getters (using core helpers)
|
|
149
|
+
// ============================================================================
|
|
150
|
+
getControllerMeta(controller) {
|
|
151
|
+
return getControllerMetadata(controller);
|
|
152
|
+
}
|
|
153
|
+
getControllerRoutes(controller) {
|
|
154
|
+
return getRoutes(controller);
|
|
155
|
+
}
|
|
156
|
+
getControllerTags(controller) {
|
|
157
|
+
return getClassMetadata(API_TAGS_METADATA, controller) || [];
|
|
158
|
+
}
|
|
159
|
+
isControllerExcluded(controller) {
|
|
160
|
+
return getClassMetadata(API_EXCLUDE_METADATA, controller) === true;
|
|
161
|
+
}
|
|
162
|
+
isControllerDeprecated(controller) {
|
|
163
|
+
return getClassMetadata(API_DEPRECATED_METADATA, controller) === true;
|
|
164
|
+
}
|
|
165
|
+
isEndpointExcluded(controller, handlerName) {
|
|
166
|
+
return getMethodMetadata(API_EXCLUDE_METADATA, controller, handlerName) === true;
|
|
167
|
+
}
|
|
168
|
+
isEndpointDeprecated(controller, handlerName) {
|
|
169
|
+
const controllerLevel = getClassMetadata(API_DEPRECATED_METADATA, controller);
|
|
170
|
+
const methodLevel = getMethodMetadata(API_DEPRECATED_METADATA, controller, handlerName);
|
|
171
|
+
return controllerLevel?.deprecated === true || methodLevel?.deprecated === true;
|
|
172
|
+
}
|
|
173
|
+
getOperationMetadata(controller, handlerName) {
|
|
174
|
+
return getMethodMetadata(API_OPERATION_METADATA, controller, handlerName);
|
|
175
|
+
}
|
|
176
|
+
getResponseMetadata(controller, handlerName) {
|
|
177
|
+
return getMethodMetadata(API_RESPONSE_METADATA, controller, handlerName) || [];
|
|
178
|
+
}
|
|
179
|
+
getBodyMetadata(controller, handlerName) {
|
|
180
|
+
return getMethodMetadata(API_BODY_METADATA, controller, handlerName);
|
|
181
|
+
}
|
|
182
|
+
getSwaggerParamMetadata(controller, handlerName) {
|
|
183
|
+
return getMethodMetadata(API_PARAM_METADATA, controller, handlerName) || [];
|
|
184
|
+
}
|
|
185
|
+
getQueryMetadata(controller, handlerName) {
|
|
186
|
+
return getMethodMetadata(API_QUERY_METADATA, controller, handlerName) || [];
|
|
187
|
+
}
|
|
188
|
+
getHeaderMetadata(controller, handlerName) {
|
|
189
|
+
return getMethodMetadata(API_HEADER_METADATA, controller, handlerName) || [];
|
|
190
|
+
}
|
|
191
|
+
getSecurityMetadata(controller, handlerName) {
|
|
192
|
+
const controllerLevel = getClassMetadata(API_SECURITY_METADATA, controller);
|
|
193
|
+
const methodLevel = getMethodMetadata(API_SECURITY_METADATA, controller, handlerName);
|
|
194
|
+
const result = [];
|
|
195
|
+
// Controller level can be a single object or null (to remove security)
|
|
196
|
+
if (controllerLevel && typeof controllerLevel === 'object' && 'name' in controllerLevel) {
|
|
197
|
+
result.push(controllerLevel);
|
|
198
|
+
}
|
|
199
|
+
else if (Array.isArray(controllerLevel)) {
|
|
200
|
+
result.push(...controllerLevel);
|
|
201
|
+
}
|
|
202
|
+
// Method level can override or add to controller level
|
|
203
|
+
if (methodLevel && typeof methodLevel === 'object' && 'name' in methodLevel) {
|
|
204
|
+
result.push(methodLevel);
|
|
205
|
+
}
|
|
206
|
+
else if (Array.isArray(methodLevel)) {
|
|
207
|
+
result.push(...methodLevel);
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
getMethodTags(controller, handlerName) {
|
|
212
|
+
const operation = this.getOperationMetadata(controller, handlerName);
|
|
213
|
+
return operation?.tags;
|
|
214
|
+
}
|
|
215
|
+
getHttpStatusCode(controller, handlerName) {
|
|
216
|
+
return getHttpCode(controller, handlerName);
|
|
217
|
+
}
|
|
218
|
+
getCoreParams(controller, handlerName) {
|
|
219
|
+
return getCoreParamMetadata(controller, handlerName);
|
|
220
|
+
}
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// Private: Path Utilities
|
|
223
|
+
// ============================================================================
|
|
224
|
+
normalizePath(prefix, path) {
|
|
225
|
+
// Ensure prefix starts with / and path handling
|
|
226
|
+
let fullPath = '';
|
|
227
|
+
if (prefix) {
|
|
228
|
+
fullPath = prefix.startsWith('/') ? prefix : `/${prefix}`;
|
|
229
|
+
}
|
|
230
|
+
if (path) {
|
|
231
|
+
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
232
|
+
fullPath = fullPath + cleanPath;
|
|
233
|
+
}
|
|
234
|
+
// Handle root path
|
|
235
|
+
if (!fullPath) {
|
|
236
|
+
fullPath = '/';
|
|
237
|
+
}
|
|
238
|
+
// Convert :param to {param} (Fastify to OpenAPI format)
|
|
239
|
+
fullPath = fullPath.replace(/:([^/]+)/g, '{$1}');
|
|
240
|
+
// Remove trailing slash (except for root)
|
|
241
|
+
if (fullPath !== '/' && fullPath.endsWith('/')) {
|
|
242
|
+
fullPath = fullPath.slice(0, -1);
|
|
243
|
+
}
|
|
244
|
+
return fullPath;
|
|
245
|
+
}
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Private: Operation Builder
|
|
248
|
+
// ============================================================================
|
|
249
|
+
buildOperation(controller, route, controllerTags, controllerDeprecated) {
|
|
250
|
+
const handlerName = route.handlerName;
|
|
251
|
+
const operationMeta = this.getOperationMetadata(controller, handlerName);
|
|
252
|
+
const methodTags = this.getMethodTags(controller, handlerName);
|
|
253
|
+
const operation = {
|
|
254
|
+
responses: {},
|
|
255
|
+
};
|
|
256
|
+
// Tags (method level overrides controller level)
|
|
257
|
+
const tags = methodTags || controllerTags;
|
|
258
|
+
if (tags.length > 0) {
|
|
259
|
+
operation.tags = tags;
|
|
260
|
+
}
|
|
261
|
+
// Summary and description from @ApiOperation
|
|
262
|
+
if (operationMeta?.summary) {
|
|
263
|
+
operation.summary = operationMeta.summary;
|
|
264
|
+
}
|
|
265
|
+
if (operationMeta?.description) {
|
|
266
|
+
operation.description = operationMeta.description;
|
|
267
|
+
}
|
|
268
|
+
if (operationMeta?.operationId) {
|
|
269
|
+
operation.operationId = operationMeta.operationId;
|
|
270
|
+
}
|
|
271
|
+
// Deprecated flag
|
|
272
|
+
if (controllerDeprecated || operationMeta?.deprecated || this.isEndpointDeprecated(controller, handlerName)) {
|
|
273
|
+
operation.deprecated = true;
|
|
274
|
+
}
|
|
275
|
+
// Parameters (path, query, header)
|
|
276
|
+
const parameters = this.buildParameters(controller, handlerName, route.path);
|
|
277
|
+
if (parameters.length > 0) {
|
|
278
|
+
operation.parameters = parameters;
|
|
279
|
+
}
|
|
280
|
+
// Request body (for POST, PUT, PATCH)
|
|
281
|
+
if (['POST', 'PUT', 'PATCH'].includes(route.method)) {
|
|
282
|
+
const requestBody = this.buildRequestBody(controller, handlerName);
|
|
283
|
+
if (requestBody) {
|
|
284
|
+
operation.requestBody = requestBody;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// Responses
|
|
288
|
+
operation.responses = this.buildResponses(controller, handlerName, route.statusCode);
|
|
289
|
+
// Security
|
|
290
|
+
const security = this.getSecurityMetadata(controller, handlerName);
|
|
291
|
+
if (security.length > 0) {
|
|
292
|
+
operation.security = security.map(s => ({ [s.name]: s.scopes || [] }));
|
|
293
|
+
}
|
|
294
|
+
return operation;
|
|
295
|
+
}
|
|
296
|
+
buildParameters(controller, handlerName, routePath) {
|
|
297
|
+
const parameters = [];
|
|
298
|
+
// Extract path parameters from route pattern
|
|
299
|
+
const pathParams = this.extractPathParams(routePath);
|
|
300
|
+
const paramDecorators = this.getSwaggerParamMetadata(controller, handlerName);
|
|
301
|
+
const queryDecorators = this.getQueryMetadata(controller, handlerName);
|
|
302
|
+
const headerDecorators = this.getHeaderMetadata(controller, handlerName);
|
|
303
|
+
const coreParams = this.getCoreParams(controller, handlerName);
|
|
304
|
+
// Add path parameters from decorator metadata or extract from path
|
|
305
|
+
const usedPathParams = new Set();
|
|
306
|
+
for (const param of paramDecorators) {
|
|
307
|
+
usedPathParams.add(param.name);
|
|
308
|
+
const baseSchema = toOpenApiSchema(param.schema);
|
|
309
|
+
const fallbackSchema = {
|
|
310
|
+
type: param.type || 'string'
|
|
311
|
+
};
|
|
312
|
+
if (param.format) {
|
|
313
|
+
fallbackSchema.format = param.format;
|
|
314
|
+
}
|
|
315
|
+
parameters.push({
|
|
316
|
+
name: param.name,
|
|
317
|
+
in: 'path',
|
|
318
|
+
required: true, // Path params are always required
|
|
319
|
+
deprecated: param.deprecated,
|
|
320
|
+
description: param.description,
|
|
321
|
+
schema: baseSchema || fallbackSchema,
|
|
322
|
+
example: param.example,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
// Add any path parameters not covered by decorators
|
|
326
|
+
for (const paramName of pathParams) {
|
|
327
|
+
if (!usedPathParams.has(paramName)) {
|
|
328
|
+
// Check if there's a Zod schema for this parameter
|
|
329
|
+
const coreParam = coreParams.find(p => p.type === ParamType.PARAM && p.key === paramName);
|
|
330
|
+
const schema = coreParam?.zodSchema ? zodToOpenApi(coreParam.zodSchema) : { type: 'string' };
|
|
331
|
+
parameters.push({
|
|
332
|
+
name: paramName,
|
|
333
|
+
in: 'path',
|
|
334
|
+
required: true,
|
|
335
|
+
schema,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Add query parameters
|
|
340
|
+
for (const query of queryDecorators) {
|
|
341
|
+
const baseSchema = toOpenApiSchema(query.schema);
|
|
342
|
+
const fallbackSchema = {
|
|
343
|
+
type: query.type || 'string'
|
|
344
|
+
};
|
|
345
|
+
if (query.format) {
|
|
346
|
+
fallbackSchema.format = query.format;
|
|
347
|
+
}
|
|
348
|
+
parameters.push({
|
|
349
|
+
name: query.name,
|
|
350
|
+
in: 'query',
|
|
351
|
+
required: query.required,
|
|
352
|
+
deprecated: query.deprecated,
|
|
353
|
+
description: query.description,
|
|
354
|
+
schema: baseSchema || fallbackSchema,
|
|
355
|
+
example: query.example,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
// Add header parameters
|
|
359
|
+
for (const header of headerDecorators) {
|
|
360
|
+
parameters.push({
|
|
361
|
+
name: header.name,
|
|
362
|
+
in: 'header',
|
|
363
|
+
required: header.required,
|
|
364
|
+
deprecated: header.deprecated,
|
|
365
|
+
description: header.description,
|
|
366
|
+
schema: toOpenApiSchema(header.schema) || {
|
|
367
|
+
type: header.type || 'string'
|
|
368
|
+
},
|
|
369
|
+
example: header.example,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return parameters;
|
|
373
|
+
}
|
|
374
|
+
extractPathParams(path) {
|
|
375
|
+
const params = [];
|
|
376
|
+
// Match both :param (Fastify) and {param} (OpenAPI) formats
|
|
377
|
+
const regex = /:([^/]+)|{([^}]+)}/g;
|
|
378
|
+
let match;
|
|
379
|
+
while ((match = regex.exec(path)) !== null) {
|
|
380
|
+
const paramName = match[1] ?? match[2];
|
|
381
|
+
if (paramName) {
|
|
382
|
+
params.push(paramName);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return params;
|
|
386
|
+
}
|
|
387
|
+
buildRequestBody(controller, handlerName) {
|
|
388
|
+
const bodyMeta = this.getBodyMetadata(controller, handlerName);
|
|
389
|
+
const coreParams = this.getCoreParams(controller, handlerName);
|
|
390
|
+
// Check for @ApiBody decorator first
|
|
391
|
+
if (bodyMeta) {
|
|
392
|
+
const schema = toOpenApiSchema(bodyMeta.schema);
|
|
393
|
+
return {
|
|
394
|
+
description: bodyMeta.description,
|
|
395
|
+
required: bodyMeta.required ?? true,
|
|
396
|
+
content: {
|
|
397
|
+
[bodyMeta.type || 'application/json']: {
|
|
398
|
+
schema: bodyMeta.isArray && schema ? { type: 'array', items: schema } : schema,
|
|
399
|
+
example: bodyMeta.example,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
// Fallback: check for @Body() decorator with Zod schema
|
|
405
|
+
const bodyParam = coreParams.find(p => p.type === ParamType.BODY);
|
|
406
|
+
if (bodyParam?.zodSchema) {
|
|
407
|
+
return {
|
|
408
|
+
required: true,
|
|
409
|
+
content: {
|
|
410
|
+
'application/json': {
|
|
411
|
+
schema: zodToOpenApi(bodyParam.zodSchema),
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
buildResponses(controller, handlerName, defaultStatusCode) {
|
|
419
|
+
const responses = {};
|
|
420
|
+
const responseMeta = this.getResponseMetadata(controller, handlerName);
|
|
421
|
+
const httpCode = this.getHttpStatusCode(controller, handlerName);
|
|
422
|
+
if (responseMeta.length > 0) {
|
|
423
|
+
for (const response of responseMeta) {
|
|
424
|
+
const statusCode = response.status.toString();
|
|
425
|
+
const schema = toOpenApiSchema(response.schema);
|
|
426
|
+
responses[statusCode] = {
|
|
427
|
+
description: response.description || this.getDefaultStatusDescription(response.status),
|
|
428
|
+
};
|
|
429
|
+
if (schema || response.example) {
|
|
430
|
+
responses[statusCode].content = {
|
|
431
|
+
[response.type || 'application/json']: {
|
|
432
|
+
schema: response.isArray && schema ? { type: 'array', items: schema } : schema,
|
|
433
|
+
example: response.example,
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
// Add default response based on HTTP code
|
|
441
|
+
const status = (httpCode || defaultStatusCode || 200).toString();
|
|
442
|
+
responses[status] = {
|
|
443
|
+
description: this.getDefaultStatusDescription(Number(status)),
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
return responses;
|
|
447
|
+
}
|
|
448
|
+
getDefaultStatusDescription(status) {
|
|
449
|
+
const descriptions = {
|
|
450
|
+
200: 'Successful response',
|
|
451
|
+
201: 'Resource created successfully',
|
|
452
|
+
204: 'No content',
|
|
453
|
+
400: 'Bad request',
|
|
454
|
+
401: 'Unauthorized',
|
|
455
|
+
403: 'Forbidden',
|
|
456
|
+
404: 'Not found',
|
|
457
|
+
409: 'Conflict',
|
|
458
|
+
422: 'Unprocessable entity',
|
|
459
|
+
500: 'Internal server error',
|
|
460
|
+
};
|
|
461
|
+
return descriptions[status] || 'Response';
|
|
462
|
+
}
|
|
463
|
+
buildSecuritySchemes() {
|
|
464
|
+
const schemes = {};
|
|
465
|
+
for (const [name, options] of this.globalSecuritySchemes) {
|
|
466
|
+
schemes[name] = {
|
|
467
|
+
type: options.type,
|
|
468
|
+
description: options.description,
|
|
469
|
+
};
|
|
470
|
+
if (options.type === 'apiKey') {
|
|
471
|
+
schemes[name].name = options.name;
|
|
472
|
+
schemes[name].in = options.in;
|
|
473
|
+
}
|
|
474
|
+
else if (options.type === 'http') {
|
|
475
|
+
schemes[name].scheme = options.scheme;
|
|
476
|
+
if (options.bearerFormat) {
|
|
477
|
+
schemes[name].bearerFormat = options.bearerFormat;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
else if (options.type === 'oauth2' && options.flows) {
|
|
481
|
+
schemes[name].flows = options.flows;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return schemes;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Create a new OpenAPI generator instance
|
|
489
|
+
*/
|
|
490
|
+
export function createOpenApiGenerator(config) {
|
|
491
|
+
return new OpenApiGenerator(config);
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/openapi/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI generation utilities barrel export
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
export { zodToOpenApi, isZodSchema, toOpenApiSchema } from './zod-to-openapi.js';
|
|
7
|
+
export { OpenApiGenerator, createOpenApiGenerator } from './generator.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openapi/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGjF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI generation utilities barrel export
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
// Zod to OpenAPI converter
|
|
7
|
+
export { zodToOpenApi, isZodSchema, toOpenApiSchema } from './zod-to-openapi.js';
|
|
8
|
+
// OpenAPI specification generator
|
|
9
|
+
export { OpenApiGenerator, createOpenApiGenerator } from './generator.js';
|
|
10
|
+
// export * from './generator.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/openapi/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEjF,kCAAkC;AAClC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC1E,kCAAkC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ZodType, ZodTypeDef } from 'zod';
|
|
2
|
+
import type { OpenApiSchemaObject } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if a value is a Zod schema
|
|
5
|
+
* Uses duck typing to detect Zod schemas without requiring the full library
|
|
6
|
+
*/
|
|
7
|
+
export declare function isZodSchema(value: unknown): value is ZodType<unknown, ZodTypeDef, unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* Convert a Zod schema to an OpenAPI 3.0 schema object
|
|
10
|
+
*
|
|
11
|
+
* Uses `zod-to-json-schema` for the heavy lifting, then converts
|
|
12
|
+
* JSON Schema 7 to OpenAPI 3.0 compatible format.
|
|
13
|
+
*
|
|
14
|
+
* Supports all Zod types including:
|
|
15
|
+
* - Primitives: string, number, boolean, bigint
|
|
16
|
+
* - Complex: object, array, tuple, record
|
|
17
|
+
* - Modifiers: optional, nullable, default
|
|
18
|
+
* - Validators: min, max, email, uuid, url, etc.
|
|
19
|
+
* - Enums: enum, nativeEnum
|
|
20
|
+
* - Unions and intersections
|
|
21
|
+
* - Literals
|
|
22
|
+
* - Effects (transform, refine)
|
|
23
|
+
*
|
|
24
|
+
* @param schema - The Zod schema to convert
|
|
25
|
+
* @returns OpenAPI schema object
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const UserSchema = z.object({
|
|
30
|
+
* id: z.string().uuid(),
|
|
31
|
+
* email: z.string().email(),
|
|
32
|
+
* age: z.number().int().min(0).optional(),
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const openApiSchema = zodToOpenApi(UserSchema);
|
|
36
|
+
* // {
|
|
37
|
+
* // type: 'object',
|
|
38
|
+
* // properties: {
|
|
39
|
+
* // id: { type: 'string', format: 'uuid' },
|
|
40
|
+
* // email: { type: 'string', format: 'email' },
|
|
41
|
+
* // age: { type: 'integer', minimum: 0 }
|
|
42
|
+
* // },
|
|
43
|
+
* // required: ['id', 'email']
|
|
44
|
+
* // }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function zodToOpenApi(schema: ZodType): OpenApiSchemaObject;
|
|
48
|
+
/**
|
|
49
|
+
* Convert a Zod schema to OpenAPI schema, or pass through if already an OpenAPI schema
|
|
50
|
+
*/
|
|
51
|
+
export declare function toOpenApiSchema(schemaOrOpenApi: ZodType | OpenApiSchemaObject | undefined): OpenApiSchemaObject | undefined;
|
|
52
|
+
//# sourceMappingURL=zod-to-openapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-openapi.d.ts","sourceRoot":"","sources":["../../src/openapi/zod-to-openapi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAE/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAQ1F;AAyGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,mBAAmB,CAWjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,OAAO,GAAG,mBAAmB,GAAG,SAAS,GACzD,mBAAmB,GAAG,SAAS,CAWjC"}
|