@veloxts/router 0.6.57 → 0.6.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/GUIDE.md +237 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +11 -0
- package/dist/openapi/generator.d.ts +52 -0
- package/dist/openapi/generator.js +442 -0
- package/dist/openapi/index.d.ts +37 -0
- package/dist/openapi/index.js +51 -0
- package/dist/openapi/path-extractor.d.ts +212 -0
- package/dist/openapi/path-extractor.js +256 -0
- package/dist/openapi/plugin.d.ts +101 -0
- package/dist/openapi/plugin.js +228 -0
- package/dist/openapi/schema-converter.d.ts +119 -0
- package/dist/openapi/schema-converter.js +246 -0
- package/dist/openapi/security-mapper.d.ts +131 -0
- package/dist/openapi/security-mapper.js +226 -0
- package/dist/openapi/types.d.ts +437 -0
- package/dist/openapi/types.js +8 -0
- package/package.json +8 -3
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates OpenAPI 3.0.3 specifications from VeloxTS procedure collections.
|
|
5
|
+
*
|
|
6
|
+
* @module @veloxts/router/openapi/generator
|
|
7
|
+
*/
|
|
8
|
+
import { generateRestRoutes } from '../rest/adapter.js';
|
|
9
|
+
import { buildParameters, convertToOpenAPIPath, joinPaths } from './path-extractor.js';
|
|
10
|
+
import { removeSchemaProperties, zodSchemaToJsonSchema } from './schema-converter.js';
|
|
11
|
+
import { extractUsedSecuritySchemes, filterUsedSecuritySchemes, guardsToSecurity, mergeSecuritySchemes, } from './security-mapper.js';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Main Generator
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Generates an OpenAPI 3.0.3 specification from procedure collections
|
|
17
|
+
*
|
|
18
|
+
* @param collections - Array of procedure collections to document
|
|
19
|
+
* @param options - Generator options
|
|
20
|
+
* @returns Complete OpenAPI specification
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { generateOpenApiSpec } from '@veloxts/router';
|
|
25
|
+
*
|
|
26
|
+
* const spec = generateOpenApiSpec([userProcedures, postProcedures], {
|
|
27
|
+
* info: {
|
|
28
|
+
* title: 'My API',
|
|
29
|
+
* version: '1.0.0',
|
|
30
|
+
* description: 'A VeloxTS-powered API',
|
|
31
|
+
* },
|
|
32
|
+
* prefix: '/api',
|
|
33
|
+
* servers: [{ url: 'http://localhost:3030' }],
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function generateOpenApiSpec(collections, options) {
|
|
38
|
+
const prefix = options.prefix ?? '/api';
|
|
39
|
+
const paths = {};
|
|
40
|
+
const tags = [];
|
|
41
|
+
const allGuards = [];
|
|
42
|
+
// Process each collection
|
|
43
|
+
for (const collection of collections) {
|
|
44
|
+
const routes = generateRestRoutes(collection);
|
|
45
|
+
// Add tag for this namespace
|
|
46
|
+
tags.push({
|
|
47
|
+
name: collection.namespace,
|
|
48
|
+
description: options.tagDescriptions?.[collection.namespace],
|
|
49
|
+
});
|
|
50
|
+
// Process each route
|
|
51
|
+
for (const route of routes) {
|
|
52
|
+
// Build full path with prefix
|
|
53
|
+
const fullPath = joinPaths(prefix, route.path);
|
|
54
|
+
const openApiPath = convertToOpenAPIPath(fullPath);
|
|
55
|
+
// Initialize path item if not exists
|
|
56
|
+
if (!paths[openApiPath]) {
|
|
57
|
+
paths[openApiPath] = {};
|
|
58
|
+
}
|
|
59
|
+
// Collect guards for security scheme filtering
|
|
60
|
+
// Cast to unknown to avoid variance issues - we only use guard names
|
|
61
|
+
allGuards.push(...route.procedure.guards);
|
|
62
|
+
// Generate operation
|
|
63
|
+
const operation = generateOperation(route, collection.namespace, options);
|
|
64
|
+
// Add to path item
|
|
65
|
+
const method = route.method.toLowerCase();
|
|
66
|
+
paths[openApiPath][method] = operation;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Build security schemes (only include those that are used)
|
|
70
|
+
const allSchemes = mergeSecuritySchemes(options.securitySchemes);
|
|
71
|
+
const usedSchemes = extractUsedSecuritySchemes(allGuards, {
|
|
72
|
+
customMappings: options.guardToSecurityMap,
|
|
73
|
+
});
|
|
74
|
+
const securitySchemes = filterUsedSecuritySchemes(allSchemes, usedSchemes);
|
|
75
|
+
// Build the spec
|
|
76
|
+
const spec = {
|
|
77
|
+
openapi: '3.0.3',
|
|
78
|
+
info: options.info,
|
|
79
|
+
paths,
|
|
80
|
+
tags,
|
|
81
|
+
};
|
|
82
|
+
// Add optional fields
|
|
83
|
+
if (options.servers?.length) {
|
|
84
|
+
spec.servers = options.servers;
|
|
85
|
+
}
|
|
86
|
+
if (Object.keys(securitySchemes).length > 0) {
|
|
87
|
+
spec.components = { securitySchemes };
|
|
88
|
+
}
|
|
89
|
+
if (options.defaultSecurity?.length) {
|
|
90
|
+
spec.security = options.defaultSecurity;
|
|
91
|
+
}
|
|
92
|
+
if (options.externalDocs) {
|
|
93
|
+
spec.externalDocs = options.externalDocs;
|
|
94
|
+
}
|
|
95
|
+
// Add extensions
|
|
96
|
+
if (options.extensions) {
|
|
97
|
+
Object.assign(spec, options.extensions);
|
|
98
|
+
}
|
|
99
|
+
return spec;
|
|
100
|
+
}
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Operation Generation
|
|
103
|
+
// ============================================================================
|
|
104
|
+
/**
|
|
105
|
+
* Generates an OpenAPI operation from a REST route
|
|
106
|
+
*/
|
|
107
|
+
function generateOperation(route, namespace, options) {
|
|
108
|
+
const { procedure, procedureName, method, path } = route;
|
|
109
|
+
// Convert Zod schemas to JSON Schema
|
|
110
|
+
const inputSchema = procedure.inputSchema
|
|
111
|
+
? zodSchemaToJsonSchema(procedure.inputSchema)
|
|
112
|
+
: undefined;
|
|
113
|
+
const outputSchema = procedure.outputSchema
|
|
114
|
+
? zodSchemaToJsonSchema(procedure.outputSchema)
|
|
115
|
+
: undefined;
|
|
116
|
+
// Build parameters
|
|
117
|
+
const { pathParams, queryParams, pathParamNames } = buildParameters({
|
|
118
|
+
path,
|
|
119
|
+
method,
|
|
120
|
+
inputSchema,
|
|
121
|
+
});
|
|
122
|
+
// Combine all parameters
|
|
123
|
+
const parameters = [...pathParams, ...queryParams];
|
|
124
|
+
// Build request body for POST, PUT, PATCH
|
|
125
|
+
const requestBody = buildRequestBody(method, inputSchema, pathParamNames);
|
|
126
|
+
// Map guards to security requirements
|
|
127
|
+
// Cast to unknown to avoid variance issues - we only use guard names
|
|
128
|
+
const security = guardsToSecurity(procedure.guards, {
|
|
129
|
+
customMappings: options.guardToSecurityMap,
|
|
130
|
+
});
|
|
131
|
+
// Build responses
|
|
132
|
+
const responses = buildResponses(method, outputSchema, security.length > 0);
|
|
133
|
+
// Build operation
|
|
134
|
+
const operation = {
|
|
135
|
+
operationId: `${namespace}_${procedureName}`,
|
|
136
|
+
summary: inferSummary(procedureName),
|
|
137
|
+
tags: [namespace],
|
|
138
|
+
responses,
|
|
139
|
+
};
|
|
140
|
+
// Add optional fields
|
|
141
|
+
if (parameters.length > 0) {
|
|
142
|
+
operation.parameters = parameters;
|
|
143
|
+
}
|
|
144
|
+
if (requestBody) {
|
|
145
|
+
operation.requestBody = requestBody;
|
|
146
|
+
}
|
|
147
|
+
if (security.length > 0) {
|
|
148
|
+
operation.security = security;
|
|
149
|
+
}
|
|
150
|
+
return operation;
|
|
151
|
+
}
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Request Body Generation
|
|
154
|
+
// ============================================================================
|
|
155
|
+
/**
|
|
156
|
+
* Builds a request body definition for mutation methods
|
|
157
|
+
*/
|
|
158
|
+
function buildRequestBody(method, inputSchema, pathParamNames) {
|
|
159
|
+
// Only POST, PUT, PATCH have request bodies
|
|
160
|
+
if (!['POST', 'PUT', 'PATCH'].includes(method)) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
if (!inputSchema) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
// Remove path parameters from body schema
|
|
167
|
+
const bodySchema = removeSchemaProperties(inputSchema, pathParamNames);
|
|
168
|
+
// If no properties left, no body needed
|
|
169
|
+
if (!bodySchema || !hasProperties(bodySchema)) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
required: true,
|
|
174
|
+
content: {
|
|
175
|
+
'application/json': {
|
|
176
|
+
schema: bodySchema,
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Checks if a schema has any properties
|
|
183
|
+
*/
|
|
184
|
+
function hasProperties(schema) {
|
|
185
|
+
if (schema.type !== 'object')
|
|
186
|
+
return true; // Non-object schemas are valid
|
|
187
|
+
if (!schema.properties)
|
|
188
|
+
return false;
|
|
189
|
+
return Object.keys(schema.properties).length > 0;
|
|
190
|
+
}
|
|
191
|
+
// ============================================================================
|
|
192
|
+
// Response Generation
|
|
193
|
+
// ============================================================================
|
|
194
|
+
/**
|
|
195
|
+
* Builds response definitions for an operation
|
|
196
|
+
*/
|
|
197
|
+
function buildResponses(method, outputSchema, hasAuth) {
|
|
198
|
+
const responses = {};
|
|
199
|
+
// Determine success status code
|
|
200
|
+
const successCode = getSuccessStatusCode(method);
|
|
201
|
+
const successDescription = getSuccessDescription(method);
|
|
202
|
+
// Success response
|
|
203
|
+
if (successCode === '204') {
|
|
204
|
+
// No content
|
|
205
|
+
responses['204'] = { description: successDescription };
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
responses[successCode] = {
|
|
209
|
+
description: successDescription,
|
|
210
|
+
...(outputSchema && {
|
|
211
|
+
content: {
|
|
212
|
+
'application/json': { schema: outputSchema },
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
// Error responses
|
|
218
|
+
responses['400'] = {
|
|
219
|
+
description: 'Bad Request - Validation error',
|
|
220
|
+
content: {
|
|
221
|
+
'application/json': {
|
|
222
|
+
schema: {
|
|
223
|
+
type: 'object',
|
|
224
|
+
properties: {
|
|
225
|
+
error: {
|
|
226
|
+
type: 'object',
|
|
227
|
+
properties: {
|
|
228
|
+
code: { type: 'string', example: 'VALIDATION_ERROR' },
|
|
229
|
+
message: { type: 'string' },
|
|
230
|
+
details: { type: 'object' },
|
|
231
|
+
},
|
|
232
|
+
required: ['code', 'message'],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
required: ['error'],
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
// Auth-related responses
|
|
241
|
+
if (hasAuth) {
|
|
242
|
+
responses['401'] = {
|
|
243
|
+
description: 'Unauthorized - Authentication required',
|
|
244
|
+
content: {
|
|
245
|
+
'application/json': {
|
|
246
|
+
schema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
error: {
|
|
250
|
+
type: 'object',
|
|
251
|
+
properties: {
|
|
252
|
+
code: { type: 'string', example: 'UNAUTHORIZED' },
|
|
253
|
+
message: { type: 'string' },
|
|
254
|
+
},
|
|
255
|
+
required: ['code', 'message'],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
required: ['error'],
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
responses['403'] = {
|
|
264
|
+
description: 'Forbidden - Insufficient permissions',
|
|
265
|
+
content: {
|
|
266
|
+
'application/json': {
|
|
267
|
+
schema: {
|
|
268
|
+
type: 'object',
|
|
269
|
+
properties: {
|
|
270
|
+
error: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: {
|
|
273
|
+
code: { type: 'string', example: 'FORBIDDEN' },
|
|
274
|
+
message: { type: 'string' },
|
|
275
|
+
},
|
|
276
|
+
required: ['code', 'message'],
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
required: ['error'],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
// Not found for single-resource operations
|
|
286
|
+
if (['GET', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
|
|
287
|
+
responses['404'] = {
|
|
288
|
+
description: 'Not Found - Resource does not exist',
|
|
289
|
+
content: {
|
|
290
|
+
'application/json': {
|
|
291
|
+
schema: {
|
|
292
|
+
type: 'object',
|
|
293
|
+
properties: {
|
|
294
|
+
error: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
code: { type: 'string', example: 'NOT_FOUND' },
|
|
298
|
+
message: { type: 'string' },
|
|
299
|
+
},
|
|
300
|
+
required: ['code', 'message'],
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
required: ['error'],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
// Internal server error
|
|
310
|
+
responses['500'] = {
|
|
311
|
+
description: 'Internal Server Error',
|
|
312
|
+
content: {
|
|
313
|
+
'application/json': {
|
|
314
|
+
schema: {
|
|
315
|
+
type: 'object',
|
|
316
|
+
properties: {
|
|
317
|
+
error: {
|
|
318
|
+
type: 'object',
|
|
319
|
+
properties: {
|
|
320
|
+
code: { type: 'string', example: 'INTERNAL_ERROR' },
|
|
321
|
+
message: { type: 'string' },
|
|
322
|
+
},
|
|
323
|
+
required: ['code', 'message'],
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
required: ['error'],
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
return responses;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Gets the success status code for an HTTP method
|
|
335
|
+
*/
|
|
336
|
+
function getSuccessStatusCode(method) {
|
|
337
|
+
switch (method) {
|
|
338
|
+
case 'POST':
|
|
339
|
+
return '201';
|
|
340
|
+
case 'DELETE':
|
|
341
|
+
return '204';
|
|
342
|
+
default:
|
|
343
|
+
return '200';
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Gets the success description for an HTTP method
|
|
348
|
+
*/
|
|
349
|
+
function getSuccessDescription(method) {
|
|
350
|
+
switch (method) {
|
|
351
|
+
case 'POST':
|
|
352
|
+
return 'Created';
|
|
353
|
+
case 'DELETE':
|
|
354
|
+
return 'No Content';
|
|
355
|
+
case 'PUT':
|
|
356
|
+
case 'PATCH':
|
|
357
|
+
return 'Updated';
|
|
358
|
+
default:
|
|
359
|
+
return 'Success';
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// ============================================================================
|
|
363
|
+
// Summary Generation
|
|
364
|
+
// ============================================================================
|
|
365
|
+
/**
|
|
366
|
+
* Infers a human-readable summary from a procedure name
|
|
367
|
+
*
|
|
368
|
+
* Converts camelCase to Title Case with spaces.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```typescript
|
|
372
|
+
* inferSummary('getUser') // 'Get User'
|
|
373
|
+
* inferSummary('createPost') // 'Create Post'
|
|
374
|
+
* inferSummary('listUsers') // 'List Users'
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
function inferSummary(procedureName) {
|
|
378
|
+
// Insert space before capital letters
|
|
379
|
+
const spaced = procedureName.replace(/([A-Z])/g, ' $1').trim();
|
|
380
|
+
// Capitalize first letter
|
|
381
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
382
|
+
}
|
|
383
|
+
// ============================================================================
|
|
384
|
+
// Utility Functions
|
|
385
|
+
// ============================================================================
|
|
386
|
+
/**
|
|
387
|
+
* Gets route summary information for debugging/logging
|
|
388
|
+
*
|
|
389
|
+
* @param collections - Procedure collections
|
|
390
|
+
* @param prefix - API prefix
|
|
391
|
+
* @returns Array of route summaries
|
|
392
|
+
*/
|
|
393
|
+
export function getOpenApiRouteSummary(collections, prefix = '/api') {
|
|
394
|
+
const routes = [];
|
|
395
|
+
for (const collection of collections) {
|
|
396
|
+
const collectionRoutes = generateRestRoutes(collection);
|
|
397
|
+
for (const route of collectionRoutes) {
|
|
398
|
+
const fullPath = joinPaths(prefix, route.path);
|
|
399
|
+
routes.push({
|
|
400
|
+
method: route.method,
|
|
401
|
+
path: convertToOpenAPIPath(fullPath),
|
|
402
|
+
operationId: `${collection.namespace}_${route.procedureName}`,
|
|
403
|
+
namespace: collection.namespace,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return routes;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Validates an OpenAPI spec for common issues
|
|
411
|
+
*
|
|
412
|
+
* @param spec - OpenAPI spec to validate
|
|
413
|
+
* @returns Array of validation warnings
|
|
414
|
+
*/
|
|
415
|
+
export function validateOpenApiSpec(spec) {
|
|
416
|
+
const warnings = [];
|
|
417
|
+
// Check for empty paths
|
|
418
|
+
if (Object.keys(spec.paths).length === 0) {
|
|
419
|
+
warnings.push('OpenAPI spec has no paths defined');
|
|
420
|
+
}
|
|
421
|
+
// Check for missing info
|
|
422
|
+
if (!spec.info.title) {
|
|
423
|
+
warnings.push('OpenAPI spec is missing info.title');
|
|
424
|
+
}
|
|
425
|
+
if (!spec.info.version) {
|
|
426
|
+
warnings.push('OpenAPI spec is missing info.version');
|
|
427
|
+
}
|
|
428
|
+
// Check for duplicate operation IDs
|
|
429
|
+
const operationIds = new Set();
|
|
430
|
+
for (const pathItem of Object.values(spec.paths)) {
|
|
431
|
+
for (const method of ['get', 'post', 'put', 'patch', 'delete']) {
|
|
432
|
+
const operation = pathItem[method];
|
|
433
|
+
if (operation?.operationId) {
|
|
434
|
+
if (operationIds.has(operation.operationId)) {
|
|
435
|
+
warnings.push(`Duplicate operationId: ${operation.operationId}`);
|
|
436
|
+
}
|
|
437
|
+
operationIds.add(operation.operationId);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return warnings;
|
|
442
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Module
|
|
3
|
+
*
|
|
4
|
+
* Generates OpenAPI 3.0.3 specifications from VeloxTS procedure collections.
|
|
5
|
+
*
|
|
6
|
+
* @module @veloxts/router/openapi
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import {
|
|
11
|
+
* generateOpenApiSpec,
|
|
12
|
+
* swaggerUIPlugin,
|
|
13
|
+
* createSwaggerUI,
|
|
14
|
+
* } from '@veloxts/router';
|
|
15
|
+
*
|
|
16
|
+
* // Generate spec programmatically
|
|
17
|
+
* const spec = generateOpenApiSpec([userProcedures, postProcedures], {
|
|
18
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
19
|
+
* prefix: '/api',
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Or register Swagger UI plugin
|
|
23
|
+
* app.register(swaggerUIPlugin, {
|
|
24
|
+
* routePrefix: '/docs',
|
|
25
|
+
* collections: [userProcedures],
|
|
26
|
+
* openapi: {
|
|
27
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export { generateOpenApiSpec, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
|
|
33
|
+
export { createSwaggerUI, getOpenApiSpec, registerDocs, swaggerUIPlugin, } from './plugin.js';
|
|
34
|
+
export { createStringSchema, extractSchemaProperties, mergeSchemas, removeSchemaProperties, type SchemaConversionOptions, schemaHasProperties, zodSchemaToJsonSchema, } from './schema-converter.js';
|
|
35
|
+
export { type BuildParametersOptions, type BuildParametersResult, buildParameters, convertFromOpenAPIPath, convertToOpenAPIPath, extractPathParamNames, extractQueryParameters, extractResourceFromPath, hasPathParameters, joinPaths, normalizePath, parsePathParameters, type QueryParamExtractionOptions, } from './path-extractor.js';
|
|
36
|
+
export { createSecurityRequirement, DEFAULT_GUARD_MAPPINGS, DEFAULT_SECURITY_SCHEMES, extractGuardScopes, extractUsedSecuritySchemes, filterUsedSecuritySchemes, type GuardMappingOptions, guardsRequireAuth, guardsToSecurity, mapGuardToSecurity, mergeSecuritySchemes, } from './security-mapper.js';
|
|
37
|
+
export type { JSONSchema, OpenAPIComponents, OpenAPIContact, OpenAPIEncoding, OpenAPIExample, OpenAPIExternalDocs, OpenAPIGeneratorOptions, OpenAPIHeader, OpenAPIHttpMethod, OpenAPIInfo, OpenAPILicense, OpenAPILink, OpenAPIMediaType, OpenAPIOAuthFlow, OpenAPIOAuthFlows, OpenAPIOperation, OpenAPIParameter, OpenAPIPathItem, OpenAPIRequestBody, OpenAPIResponse, OpenAPISecurityRequirement, OpenAPISecurityScheme, OpenAPIServer, OpenAPISpec, OpenAPITag, ParameterIn, RouteInfo, SecuritySchemeType, SwaggerUIConfig, SwaggerUIPluginOptions, } from './types.js';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI Module
|
|
3
|
+
*
|
|
4
|
+
* Generates OpenAPI 3.0.3 specifications from VeloxTS procedure collections.
|
|
5
|
+
*
|
|
6
|
+
* @module @veloxts/router/openapi
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import {
|
|
11
|
+
* generateOpenApiSpec,
|
|
12
|
+
* swaggerUIPlugin,
|
|
13
|
+
* createSwaggerUI,
|
|
14
|
+
* } from '@veloxts/router';
|
|
15
|
+
*
|
|
16
|
+
* // Generate spec programmatically
|
|
17
|
+
* const spec = generateOpenApiSpec([userProcedures, postProcedures], {
|
|
18
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
19
|
+
* prefix: '/api',
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Or register Swagger UI plugin
|
|
23
|
+
* app.register(swaggerUIPlugin, {
|
|
24
|
+
* routePrefix: '/docs',
|
|
25
|
+
* collections: [userProcedures],
|
|
26
|
+
* openapi: {
|
|
27
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Generator
|
|
34
|
+
// ============================================================================
|
|
35
|
+
export { generateOpenApiSpec, getOpenApiRouteSummary, validateOpenApiSpec, } from './generator.js';
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Plugin
|
|
38
|
+
// ============================================================================
|
|
39
|
+
export { createSwaggerUI, getOpenApiSpec, registerDocs, swaggerUIPlugin, } from './plugin.js';
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Schema Converter
|
|
42
|
+
// ============================================================================
|
|
43
|
+
export { createStringSchema, extractSchemaProperties, mergeSchemas, removeSchemaProperties, schemaHasProperties, zodSchemaToJsonSchema, } from './schema-converter.js';
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Path Extractor
|
|
46
|
+
// ============================================================================
|
|
47
|
+
export { buildParameters, convertFromOpenAPIPath, convertToOpenAPIPath, extractPathParamNames, extractQueryParameters, extractResourceFromPath, hasPathParameters, joinPaths, normalizePath, parsePathParameters, } from './path-extractor.js';
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Security Mapper
|
|
50
|
+
// ============================================================================
|
|
51
|
+
export { createSecurityRequirement, DEFAULT_GUARD_MAPPINGS, DEFAULT_SECURITY_SCHEMES, extractGuardScopes, extractUsedSecuritySchemes, filterUsedSecuritySchemes, guardsRequireAuth, guardsToSecurity, mapGuardToSecurity, mergeSecuritySchemes, } from './security-mapper.js';
|