@riktajs/swagger 0.1.2 → 0.2.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/dist/constants.d.ts +0 -45
- package/dist/constants.js +0 -50
- package/dist/decorators/api-body.decorator.d.ts +0 -29
- package/dist/decorators/api-body.decorator.js +0 -29
- package/dist/decorators/api-exclude.decorator.d.ts +0 -62
- package/dist/decorators/api-exclude.decorator.js +0 -64
- package/dist/decorators/api-header.decorator.d.ts +0 -21
- package/dist/decorators/api-header.decorator.js +0 -21
- package/dist/decorators/api-operation.decorator.d.ts +0 -28
- package/dist/decorators/api-operation.decorator.js +0 -28
- package/dist/decorators/api-param.decorator.d.ts +0 -24
- package/dist/decorators/api-param.decorator.js +0 -24
- package/dist/decorators/api-property.decorator.d.ts +0 -58
- package/dist/decorators/api-property.decorator.js +0 -56
- package/dist/decorators/api-query.decorator.d.ts +0 -26
- package/dist/decorators/api-query.decorator.js +0 -26
- package/dist/decorators/api-response.decorator.d.ts +0 -55
- package/dist/decorators/api-response.decorator.js +0 -55
- package/dist/decorators/api-security.decorator.d.ts +0 -80
- package/dist/decorators/api-security.decorator.js +0 -84
- package/dist/decorators/api-tags.decorator.d.ts +0 -28
- package/dist/decorators/api-tags.decorator.js +0 -30
- package/dist/decorators/index.d.ts +0 -6
- package/dist/decorators/index.js +0 -14
- package/dist/index.d.ts +0 -55
- package/dist/index.js +0 -62
- package/dist/openapi/generator.d.ts +0 -49
- package/dist/openapi/generator.js +2 -86
- package/dist/openapi/index.d.ts +0 -6
- package/dist/openapi/index.js +0 -9
- package/dist/openapi/zod-to-openapi.d.ts +2 -49
- package/dist/openapi/zod-to-openapi.js +18 -75
- package/dist/plugin/index.d.ts +0 -6
- package/dist/plugin/index.js +0 -6
- package/dist/plugin/swagger.plugin.d.ts +0 -119
- package/dist/plugin/swagger.plugin.js +1 -110
- package/dist/types.d.ts +0 -173
- package/dist/types.js +0 -1
- package/package.json +62 -61
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/decorators/api-body.decorator.d.ts.map +0 -1
- package/dist/decorators/api-body.decorator.js.map +0 -1
- package/dist/decorators/api-exclude.decorator.d.ts.map +0 -1
- package/dist/decorators/api-exclude.decorator.js.map +0 -1
- package/dist/decorators/api-header.decorator.d.ts.map +0 -1
- package/dist/decorators/api-header.decorator.js.map +0 -1
- package/dist/decorators/api-operation.decorator.d.ts.map +0 -1
- package/dist/decorators/api-operation.decorator.js.map +0 -1
- package/dist/decorators/api-param.decorator.d.ts.map +0 -1
- package/dist/decorators/api-param.decorator.js.map +0 -1
- package/dist/decorators/api-property.decorator.d.ts.map +0 -1
- package/dist/decorators/api-property.decorator.js.map +0 -1
- package/dist/decorators/api-query.decorator.d.ts.map +0 -1
- package/dist/decorators/api-query.decorator.js.map +0 -1
- package/dist/decorators/api-response.decorator.d.ts.map +0 -1
- package/dist/decorators/api-response.decorator.js.map +0 -1
- package/dist/decorators/api-security.decorator.d.ts.map +0 -1
- package/dist/decorators/api-security.decorator.js.map +0 -1
- package/dist/decorators/api-tags.decorator.d.ts.map +0 -1
- package/dist/decorators/api-tags.decorator.js.map +0 -1
- package/dist/decorators/index.d.ts.map +0 -1
- package/dist/decorators/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/openapi/generator.d.ts.map +0 -1
- package/dist/openapi/generator.js.map +0 -1
- package/dist/openapi/index.d.ts.map +0 -1
- package/dist/openapi/index.js.map +0 -1
- package/dist/openapi/zod-to-openapi.d.ts.map +0 -1
- package/dist/openapi/zod-to-openapi.js.map +0 -1
- package/dist/plugin/index.d.ts.map +0 -1
- package/dist/plugin/index.js.map +0 -1
- package/dist/plugin/swagger.plugin.d.ts.map +0 -1
- package/dist/plugin/swagger.plugin.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,57 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @riktajs/swagger
|
|
3
|
-
*
|
|
4
|
-
* Automatic OpenAPI/Swagger documentation generation for Rikta Framework.
|
|
5
|
-
*
|
|
6
|
-
* This package provides decorators and utilities to automatically generate
|
|
7
|
-
* OpenAPI 3.0/3.1 documentation from your Rikta controllers and routes.
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Automatic route extraction from @Controller, @Get, @Post, etc.
|
|
11
|
-
* - Decorators for enriching API documentation (@ApiTags, @ApiOperation, @ApiResponse, etc.)
|
|
12
|
-
* - Zod schema integration for automatic request/response type documentation
|
|
13
|
-
* - Interactive Swagger UI served via Fastify
|
|
14
|
-
* - Full OpenAPI 3.0/3.1 specification support
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { Rikta, Controller, Get } from '@riktajs/core';
|
|
19
|
-
* import { swaggerPlugin, ApiTags, ApiOperation, ApiResponse } from '@riktajs/swagger';
|
|
20
|
-
* import { z } from 'zod';
|
|
21
|
-
*
|
|
22
|
-
* const UserSchema = z.object({
|
|
23
|
-
* id: z.string().uuid(),
|
|
24
|
-
* name: z.string(),
|
|
25
|
-
* email: z.string().email(),
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* @ApiTags('Users')
|
|
29
|
-
* @Controller('/users')
|
|
30
|
-
* class UserController {
|
|
31
|
-
* @Get('/')
|
|
32
|
-
* @ApiOperation({ summary: 'List all users' })
|
|
33
|
-
* @ApiResponse({ status: 200, description: 'Array of users', schema: z.array(UserSchema) })
|
|
34
|
-
* async listUsers() {
|
|
35
|
-
* return [];
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
38
|
-
*
|
|
39
|
-
* const app = await Rikta.create({ port: 3000 });
|
|
40
|
-
*
|
|
41
|
-
* // Register swagger plugin
|
|
42
|
-
* app.server.register(swaggerPlugin, {
|
|
43
|
-
* title: 'My API',
|
|
44
|
-
* version: '1.0.0',
|
|
45
|
-
* description: 'My awesome API documentation',
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* await app.listen();
|
|
49
|
-
* // Swagger UI available at http://localhost:3000/docs
|
|
50
|
-
* // OpenAPI JSON available at http://localhost:3000/docs/json
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @packageDocumentation
|
|
54
|
-
*/
|
|
55
1
|
export * from './constants.js';
|
|
56
2
|
export { CONTROLLER_METADATA, ROUTES_METADATA, PARAM_METADATA, HTTP_CODE_METADATA, GUARDS_METADATA, ZOD_SCHEMA_METADATA, } from '@riktajs/core';
|
|
57
3
|
export type * from './types.js';
|
|
@@ -59,4 +5,3 @@ export * from './decorators/index.js';
|
|
|
59
5
|
export { OpenApiGenerator } from './openapi/generator.js';
|
|
60
6
|
export { zodToOpenApi, toOpenApiSchema, isZodSchema } from './openapi/zod-to-openapi.js';
|
|
61
7
|
export { swaggerPlugin, registerSwagger, createSwaggerConfig } from './plugin/swagger.plugin.js';
|
|
62
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,68 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @riktajs/swagger
|
|
3
|
-
*
|
|
4
|
-
* Automatic OpenAPI/Swagger documentation generation for Rikta Framework.
|
|
5
|
-
*
|
|
6
|
-
* This package provides decorators and utilities to automatically generate
|
|
7
|
-
* OpenAPI 3.0/3.1 documentation from your Rikta controllers and routes.
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Automatic route extraction from @Controller, @Get, @Post, etc.
|
|
11
|
-
* - Decorators for enriching API documentation (@ApiTags, @ApiOperation, @ApiResponse, etc.)
|
|
12
|
-
* - Zod schema integration for automatic request/response type documentation
|
|
13
|
-
* - Interactive Swagger UI served via Fastify
|
|
14
|
-
* - Full OpenAPI 3.0/3.1 specification support
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { Rikta, Controller, Get } from '@riktajs/core';
|
|
19
|
-
* import { swaggerPlugin, ApiTags, ApiOperation, ApiResponse } from '@riktajs/swagger';
|
|
20
|
-
* import { z } from 'zod';
|
|
21
|
-
*
|
|
22
|
-
* const UserSchema = z.object({
|
|
23
|
-
* id: z.string().uuid(),
|
|
24
|
-
* name: z.string(),
|
|
25
|
-
* email: z.string().email(),
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* @ApiTags('Users')
|
|
29
|
-
* @Controller('/users')
|
|
30
|
-
* class UserController {
|
|
31
|
-
* @Get('/')
|
|
32
|
-
* @ApiOperation({ summary: 'List all users' })
|
|
33
|
-
* @ApiResponse({ status: 200, description: 'Array of users', schema: z.array(UserSchema) })
|
|
34
|
-
* async listUsers() {
|
|
35
|
-
* return [];
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
38
|
-
*
|
|
39
|
-
* const app = await Rikta.create({ port: 3000 });
|
|
40
|
-
*
|
|
41
|
-
* // Register swagger plugin
|
|
42
|
-
* app.server.register(swaggerPlugin, {
|
|
43
|
-
* title: 'My API',
|
|
44
|
-
* version: '1.0.0',
|
|
45
|
-
* description: 'My awesome API documentation',
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* await app.listen();
|
|
49
|
-
* // Swagger UI available at http://localhost:3000/docs
|
|
50
|
-
* // OpenAPI JSON available at http://localhost:3000/docs/json
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @packageDocumentation
|
|
54
|
-
*/
|
|
55
|
-
// Export swagger-specific constants
|
|
56
1
|
export * from './constants.js';
|
|
57
|
-
// Re-export core constants needed for metadata reading
|
|
58
|
-
// These are imported from @riktajs/core to avoid duplication
|
|
59
2
|
export { CONTROLLER_METADATA, ROUTES_METADATA, PARAM_METADATA, HTTP_CODE_METADATA, GUARDS_METADATA, ZOD_SCHEMA_METADATA, } from '@riktajs/core';
|
|
60
|
-
// Export decorators
|
|
61
3
|
export * from './decorators/index.js';
|
|
62
|
-
// Export OpenAPI generator
|
|
63
4
|
export { OpenApiGenerator } from './openapi/generator.js';
|
|
64
|
-
// Export Zod-to-OpenAPI utilities
|
|
65
5
|
export { zodToOpenApi, toOpenApiSchema, isZodSchema } from './openapi/zod-to-openapi.js';
|
|
66
|
-
// Export Fastify plugin
|
|
67
6
|
export { swaggerPlugin, registerSwagger, createSwaggerConfig } from './plugin/swagger.plugin.js';
|
|
68
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,68 +1,23 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import type { SwaggerConfig, OpenApiDocument, OpenApiSecurityScheme, OpenApiInfoObject } from '../types.js';
|
|
3
3
|
type Constructor<T = unknown> = new (...args: any[]) => T;
|
|
4
|
-
/**
|
|
5
|
-
* Shorthand config options that allow flat title/version/description
|
|
6
|
-
*/
|
|
7
4
|
interface OpenApiGeneratorConfig extends Omit<SwaggerConfig, 'info'> {
|
|
8
|
-
/** API title (shorthand for info.title) */
|
|
9
5
|
title?: string;
|
|
10
|
-
/** API version (shorthand for info.version) */
|
|
11
6
|
version?: string;
|
|
12
|
-
/** API description (shorthand for info.description) */
|
|
13
7
|
description?: string;
|
|
14
|
-
/** API contact (shorthand for info.contact) */
|
|
15
8
|
contact?: OpenApiInfoObject['contact'];
|
|
16
|
-
/** API license (shorthand for info.license) */
|
|
17
9
|
license?: OpenApiInfoObject['license'];
|
|
18
|
-
/** API terms of service (shorthand for info.termsOfService) */
|
|
19
10
|
termsOfService?: string;
|
|
20
|
-
/** Full info object (takes precedence over shorthand) */
|
|
21
11
|
info?: OpenApiInfoObject;
|
|
22
12
|
}
|
|
23
|
-
/**
|
|
24
|
-
* OpenAPI Specification Generator
|
|
25
|
-
*
|
|
26
|
-
* Collects metadata from controllers and generates a complete
|
|
27
|
-
* OpenAPI 3.0.3 specification document.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```typescript
|
|
31
|
-
* const generator = new OpenApiGenerator({
|
|
32
|
-
* info: {
|
|
33
|
-
* title: 'My API',
|
|
34
|
-
* version: '1.0.0',
|
|
35
|
-
* },
|
|
36
|
-
* });
|
|
37
|
-
*
|
|
38
|
-
* // Add controllers to scan
|
|
39
|
-
* generator.addController(UserController);
|
|
40
|
-
* generator.addController(ProductController);
|
|
41
|
-
*
|
|
42
|
-
* // Generate the specification
|
|
43
|
-
* const spec = generator.generate();
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
13
|
export declare class OpenApiGenerator {
|
|
47
14
|
private config;
|
|
48
15
|
private controllers;
|
|
49
16
|
private globalSecuritySchemes;
|
|
50
17
|
constructor(config?: OpenApiGeneratorConfig);
|
|
51
|
-
/**
|
|
52
|
-
* Add a controller to be documented
|
|
53
|
-
*/
|
|
54
18
|
addController(controller: Constructor): this;
|
|
55
|
-
/**
|
|
56
|
-
* Add multiple controllers
|
|
57
|
-
*/
|
|
58
19
|
addControllers(controllers: Constructor[]): this;
|
|
59
|
-
/**
|
|
60
|
-
* Add a global security scheme
|
|
61
|
-
*/
|
|
62
20
|
addSecurityScheme(name: string, scheme: OpenApiSecurityScheme): this;
|
|
63
|
-
/**
|
|
64
|
-
* Generate the OpenAPI specification document
|
|
65
|
-
*/
|
|
66
21
|
generate(): OpenApiDocument;
|
|
67
22
|
private getControllerMeta;
|
|
68
23
|
private getControllerRoutes;
|
|
@@ -90,9 +45,5 @@ export declare class OpenApiGenerator {
|
|
|
90
45
|
private getDefaultStatusDescription;
|
|
91
46
|
private buildSecuritySchemes;
|
|
92
47
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Create a new OpenAPI generator instance
|
|
95
|
-
*/
|
|
96
48
|
export declare function createOpenApiGenerator(config?: Partial<SwaggerConfig>): OpenApiGenerator;
|
|
97
49
|
export {};
|
|
98
|
-
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -1,47 +1,18 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import { ParamType,
|
|
3
|
-
// Metadata helper functions
|
|
4
|
-
getControllerMetadata, getRoutes, getParamMetadata as getCoreParamMetadata, getHttpCode, getClassMetadata, getMethodMetadata, } from '@riktajs/core';
|
|
2
|
+
import { ParamType, getControllerMetadata, getRoutes, getParamMetadata as getCoreParamMetadata, getHttpCode, getClassMetadata, getMethodMetadata, } from '@riktajs/core';
|
|
5
3
|
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
4
|
import { zodToOpenApi, toOpenApiSchema } from './zod-to-openapi.js';
|
|
7
|
-
/**
|
|
8
|
-
* Default swagger config values
|
|
9
|
-
*/
|
|
10
5
|
const DEFAULT_SWAGGER_CONFIG = {
|
|
11
6
|
info: {
|
|
12
7
|
title: 'API Documentation',
|
|
13
8
|
version: '1.0.0',
|
|
14
9
|
},
|
|
15
10
|
};
|
|
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
11
|
export class OpenApiGenerator {
|
|
40
12
|
config;
|
|
41
13
|
controllers = [];
|
|
42
14
|
globalSecuritySchemes = new Map();
|
|
43
15
|
constructor(config = {}) {
|
|
44
|
-
// Build info object from shorthand or full info
|
|
45
16
|
const info = config.info ?? {
|
|
46
17
|
title: config.title ?? DEFAULT_SWAGGER_CONFIG.info?.title ?? 'API Documentation',
|
|
47
18
|
version: config.version ?? DEFAULT_SWAGGER_CONFIG.info?.version ?? '1.0.0',
|
|
@@ -50,7 +21,6 @@ export class OpenApiGenerator {
|
|
|
50
21
|
license: config.license,
|
|
51
22
|
termsOfService: config.termsOfService,
|
|
52
23
|
};
|
|
53
|
-
// Extract remaining config (excluding shorthand properties)
|
|
54
24
|
const { title, version, description, contact, license, termsOfService, ...restConfig } = config;
|
|
55
25
|
this.config = {
|
|
56
26
|
...DEFAULT_SWAGGER_CONFIG,
|
|
@@ -58,36 +28,23 @@ export class OpenApiGenerator {
|
|
|
58
28
|
info,
|
|
59
29
|
};
|
|
60
30
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Add a controller to be documented
|
|
63
|
-
*/
|
|
64
31
|
addController(controller) {
|
|
65
32
|
this.controllers.push(controller);
|
|
66
33
|
return this;
|
|
67
34
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Add multiple controllers
|
|
70
|
-
*/
|
|
71
35
|
addControllers(controllers) {
|
|
72
36
|
this.controllers.push(...controllers);
|
|
73
37
|
return this;
|
|
74
38
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Add a global security scheme
|
|
77
|
-
*/
|
|
78
39
|
addSecurityScheme(name, scheme) {
|
|
79
40
|
this.globalSecuritySchemes.set(name, scheme);
|
|
80
41
|
return this;
|
|
81
42
|
}
|
|
82
|
-
/**
|
|
83
|
-
* Generate the OpenAPI specification document
|
|
84
|
-
*/
|
|
85
43
|
generate() {
|
|
86
44
|
const paths = {};
|
|
87
45
|
const tags = [];
|
|
88
46
|
const seenTags = new Set();
|
|
89
47
|
for (const controller of this.controllers) {
|
|
90
|
-
// Check if controller is excluded
|
|
91
48
|
if (this.isControllerExcluded(controller)) {
|
|
92
49
|
continue;
|
|
93
50
|
}
|
|
@@ -96,17 +53,14 @@ export class OpenApiGenerator {
|
|
|
96
53
|
continue;
|
|
97
54
|
const controllerTags = this.getControllerTags(controller);
|
|
98
55
|
const controllerDeprecated = this.isControllerDeprecated(controller);
|
|
99
|
-
// Add controller tags to the global tags list
|
|
100
56
|
for (const tag of controllerTags) {
|
|
101
57
|
if (!seenTags.has(tag)) {
|
|
102
58
|
seenTags.add(tag);
|
|
103
59
|
tags.push({ name: tag });
|
|
104
60
|
}
|
|
105
61
|
}
|
|
106
|
-
// Process each route
|
|
107
62
|
const routes = this.getControllerRoutes(controller);
|
|
108
63
|
for (const route of routes) {
|
|
109
|
-
// Check if endpoint is excluded
|
|
110
64
|
if (this.isEndpointExcluded(controller, route.handlerName)) {
|
|
111
65
|
continue;
|
|
112
66
|
}
|
|
@@ -116,11 +70,9 @@ export class OpenApiGenerator {
|
|
|
116
70
|
paths[fullPath] = {};
|
|
117
71
|
}
|
|
118
72
|
const operation = this.buildOperation(controller, route, controllerTags, controllerDeprecated);
|
|
119
|
-
// Assign operation to the path item using method as key
|
|
120
73
|
paths[fullPath][method] = operation;
|
|
121
74
|
}
|
|
122
75
|
}
|
|
123
|
-
// Build security schemes from global and controller-level definitions
|
|
124
76
|
const securitySchemes = this.buildSecuritySchemes();
|
|
125
77
|
const document = {
|
|
126
78
|
openapi: '3.0.3',
|
|
@@ -144,9 +96,6 @@ export class OpenApiGenerator {
|
|
|
144
96
|
}
|
|
145
97
|
return document;
|
|
146
98
|
}
|
|
147
|
-
// ============================================================================
|
|
148
|
-
// Private: Metadata Getters (using core helpers)
|
|
149
|
-
// ============================================================================
|
|
150
99
|
getControllerMeta(controller) {
|
|
151
100
|
return getControllerMetadata(controller);
|
|
152
101
|
}
|
|
@@ -192,14 +141,12 @@ export class OpenApiGenerator {
|
|
|
192
141
|
const controllerLevel = getClassMetadata(API_SECURITY_METADATA, controller);
|
|
193
142
|
const methodLevel = getMethodMetadata(API_SECURITY_METADATA, controller, handlerName);
|
|
194
143
|
const result = [];
|
|
195
|
-
// Controller level can be a single object or null (to remove security)
|
|
196
144
|
if (controllerLevel && typeof controllerLevel === 'object' && 'name' in controllerLevel) {
|
|
197
145
|
result.push(controllerLevel);
|
|
198
146
|
}
|
|
199
147
|
else if (Array.isArray(controllerLevel)) {
|
|
200
148
|
result.push(...controllerLevel);
|
|
201
149
|
}
|
|
202
|
-
// Method level can override or add to controller level
|
|
203
150
|
if (methodLevel && typeof methodLevel === 'object' && 'name' in methodLevel) {
|
|
204
151
|
result.push(methodLevel);
|
|
205
152
|
}
|
|
@@ -218,11 +165,7 @@ export class OpenApiGenerator {
|
|
|
218
165
|
getCoreParams(controller, handlerName) {
|
|
219
166
|
return getCoreParamMetadata(controller, handlerName);
|
|
220
167
|
}
|
|
221
|
-
// ============================================================================
|
|
222
|
-
// Private: Path Utilities
|
|
223
|
-
// ============================================================================
|
|
224
168
|
normalizePath(prefix, path) {
|
|
225
|
-
// Ensure prefix starts with / and path handling
|
|
226
169
|
let fullPath = '';
|
|
227
170
|
if (prefix) {
|
|
228
171
|
fullPath = prefix.startsWith('/') ? prefix : `/${prefix}`;
|
|
@@ -231,21 +174,15 @@ export class OpenApiGenerator {
|
|
|
231
174
|
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
232
175
|
fullPath = fullPath + cleanPath;
|
|
233
176
|
}
|
|
234
|
-
// Handle root path
|
|
235
177
|
if (!fullPath) {
|
|
236
178
|
fullPath = '/';
|
|
237
179
|
}
|
|
238
|
-
// Convert :param to {param} (Fastify to OpenAPI format)
|
|
239
180
|
fullPath = fullPath.replace(/:([^/]+)/g, '{$1}');
|
|
240
|
-
// Remove trailing slash (except for root)
|
|
241
181
|
if (fullPath !== '/' && fullPath.endsWith('/')) {
|
|
242
182
|
fullPath = fullPath.slice(0, -1);
|
|
243
183
|
}
|
|
244
184
|
return fullPath;
|
|
245
185
|
}
|
|
246
|
-
// ============================================================================
|
|
247
|
-
// Private: Operation Builder
|
|
248
|
-
// ============================================================================
|
|
249
186
|
buildOperation(controller, route, controllerTags, controllerDeprecated) {
|
|
250
187
|
const handlerName = route.handlerName;
|
|
251
188
|
const operationMeta = this.getOperationMetadata(controller, handlerName);
|
|
@@ -253,12 +190,10 @@ export class OpenApiGenerator {
|
|
|
253
190
|
const operation = {
|
|
254
191
|
responses: {},
|
|
255
192
|
};
|
|
256
|
-
// Tags (method level overrides controller level)
|
|
257
193
|
const tags = methodTags || controllerTags;
|
|
258
194
|
if (tags.length > 0) {
|
|
259
195
|
operation.tags = tags;
|
|
260
196
|
}
|
|
261
|
-
// Summary and description from @ApiOperation
|
|
262
197
|
if (operationMeta?.summary) {
|
|
263
198
|
operation.summary = operationMeta.summary;
|
|
264
199
|
}
|
|
@@ -268,25 +203,20 @@ export class OpenApiGenerator {
|
|
|
268
203
|
if (operationMeta?.operationId) {
|
|
269
204
|
operation.operationId = operationMeta.operationId;
|
|
270
205
|
}
|
|
271
|
-
// Deprecated flag
|
|
272
206
|
if (controllerDeprecated || operationMeta?.deprecated || this.isEndpointDeprecated(controller, handlerName)) {
|
|
273
207
|
operation.deprecated = true;
|
|
274
208
|
}
|
|
275
|
-
// Parameters (path, query, header)
|
|
276
209
|
const parameters = this.buildParameters(controller, handlerName, route.path);
|
|
277
210
|
if (parameters.length > 0) {
|
|
278
211
|
operation.parameters = parameters;
|
|
279
212
|
}
|
|
280
|
-
// Request body (for POST, PUT, PATCH)
|
|
281
213
|
if (['POST', 'PUT', 'PATCH'].includes(route.method)) {
|
|
282
214
|
const requestBody = this.buildRequestBody(controller, handlerName);
|
|
283
215
|
if (requestBody) {
|
|
284
216
|
operation.requestBody = requestBody;
|
|
285
217
|
}
|
|
286
218
|
}
|
|
287
|
-
// Responses
|
|
288
219
|
operation.responses = this.buildResponses(controller, handlerName, route.statusCode);
|
|
289
|
-
// Security
|
|
290
220
|
const security = this.getSecurityMetadata(controller, handlerName);
|
|
291
221
|
if (security.length > 0) {
|
|
292
222
|
operation.security = security.map(s => ({ [s.name]: s.scopes || [] }));
|
|
@@ -295,13 +225,11 @@ export class OpenApiGenerator {
|
|
|
295
225
|
}
|
|
296
226
|
buildParameters(controller, handlerName, routePath) {
|
|
297
227
|
const parameters = [];
|
|
298
|
-
// Extract path parameters from route pattern
|
|
299
228
|
const pathParams = this.extractPathParams(routePath);
|
|
300
229
|
const paramDecorators = this.getSwaggerParamMetadata(controller, handlerName);
|
|
301
230
|
const queryDecorators = this.getQueryMetadata(controller, handlerName);
|
|
302
231
|
const headerDecorators = this.getHeaderMetadata(controller, handlerName);
|
|
303
232
|
const coreParams = this.getCoreParams(controller, handlerName);
|
|
304
|
-
// Add path parameters from decorator metadata or extract from path
|
|
305
233
|
const usedPathParams = new Set();
|
|
306
234
|
for (const param of paramDecorators) {
|
|
307
235
|
usedPathParams.add(param.name);
|
|
@@ -315,17 +243,15 @@ export class OpenApiGenerator {
|
|
|
315
243
|
parameters.push({
|
|
316
244
|
name: param.name,
|
|
317
245
|
in: 'path',
|
|
318
|
-
required: true,
|
|
246
|
+
required: true,
|
|
319
247
|
deprecated: param.deprecated,
|
|
320
248
|
description: param.description,
|
|
321
249
|
schema: baseSchema || fallbackSchema,
|
|
322
250
|
example: param.example,
|
|
323
251
|
});
|
|
324
252
|
}
|
|
325
|
-
// Add any path parameters not covered by decorators
|
|
326
253
|
for (const paramName of pathParams) {
|
|
327
254
|
if (!usedPathParams.has(paramName)) {
|
|
328
|
-
// Check if there's a Zod schema for this parameter
|
|
329
255
|
const coreParam = coreParams.find(p => p.type === ParamType.PARAM && p.key === paramName);
|
|
330
256
|
const schema = coreParam?.zodSchema ? zodToOpenApi(coreParam.zodSchema) : { type: 'string' };
|
|
331
257
|
parameters.push({
|
|
@@ -336,7 +262,6 @@ export class OpenApiGenerator {
|
|
|
336
262
|
});
|
|
337
263
|
}
|
|
338
264
|
}
|
|
339
|
-
// Add query parameters
|
|
340
265
|
for (const query of queryDecorators) {
|
|
341
266
|
const baseSchema = toOpenApiSchema(query.schema);
|
|
342
267
|
const fallbackSchema = {
|
|
@@ -355,7 +280,6 @@ export class OpenApiGenerator {
|
|
|
355
280
|
example: query.example,
|
|
356
281
|
});
|
|
357
282
|
}
|
|
358
|
-
// Add header parameters
|
|
359
283
|
for (const header of headerDecorators) {
|
|
360
284
|
parameters.push({
|
|
361
285
|
name: header.name,
|
|
@@ -373,7 +297,6 @@ export class OpenApiGenerator {
|
|
|
373
297
|
}
|
|
374
298
|
extractPathParams(path) {
|
|
375
299
|
const params = [];
|
|
376
|
-
// Match both :param (Fastify) and {param} (OpenAPI) formats
|
|
377
300
|
const regex = /:([^/]+)|{([^}]+)}/g;
|
|
378
301
|
let match;
|
|
379
302
|
while ((match = regex.exec(path)) !== null) {
|
|
@@ -387,7 +310,6 @@ export class OpenApiGenerator {
|
|
|
387
310
|
buildRequestBody(controller, handlerName) {
|
|
388
311
|
const bodyMeta = this.getBodyMetadata(controller, handlerName);
|
|
389
312
|
const coreParams = this.getCoreParams(controller, handlerName);
|
|
390
|
-
// Check for @ApiBody decorator first
|
|
391
313
|
if (bodyMeta) {
|
|
392
314
|
const schema = toOpenApiSchema(bodyMeta.schema);
|
|
393
315
|
return {
|
|
@@ -401,7 +323,6 @@ export class OpenApiGenerator {
|
|
|
401
323
|
},
|
|
402
324
|
};
|
|
403
325
|
}
|
|
404
|
-
// Fallback: check for @Body() decorator with Zod schema
|
|
405
326
|
const bodyParam = coreParams.find(p => p.type === ParamType.BODY);
|
|
406
327
|
if (bodyParam?.zodSchema) {
|
|
407
328
|
return {
|
|
@@ -437,7 +358,6 @@ export class OpenApiGenerator {
|
|
|
437
358
|
}
|
|
438
359
|
}
|
|
439
360
|
else {
|
|
440
|
-
// Add default response based on HTTP code
|
|
441
361
|
const status = (httpCode || defaultStatusCode || 200).toString();
|
|
442
362
|
responses[status] = {
|
|
443
363
|
description: this.getDefaultStatusDescription(Number(status)),
|
|
@@ -484,10 +404,6 @@ export class OpenApiGenerator {
|
|
|
484
404
|
return schemes;
|
|
485
405
|
}
|
|
486
406
|
}
|
|
487
|
-
/**
|
|
488
|
-
* Create a new OpenAPI generator instance
|
|
489
|
-
*/
|
|
490
407
|
export function createOpenApiGenerator(config) {
|
|
491
408
|
return new OpenApiGenerator(config);
|
|
492
409
|
}
|
|
493
|
-
//# sourceMappingURL=generator.js.map
|
package/dist/openapi/index.d.ts
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenAPI generation utilities barrel export
|
|
3
|
-
*
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
1
|
export { zodToOpenApi, isZodSchema, toOpenApiSchema } from './zod-to-openapi.js';
|
|
7
2
|
export { OpenApiGenerator, createOpenApiGenerator } from './generator.js';
|
|
8
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/openapi/index.js
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenAPI generation utilities barrel export
|
|
3
|
-
*
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
// Zod to OpenAPI converter
|
|
7
1
|
export { zodToOpenApi, isZodSchema, toOpenApiSchema } from './zod-to-openapi.js';
|
|
8
|
-
// OpenAPI specification generator
|
|
9
2
|
export { OpenApiGenerator, createOpenApiGenerator } from './generator.js';
|
|
10
|
-
// export * from './generator.js';
|
|
11
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,52 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ZodType } from 'zod';
|
|
2
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
|
-
*/
|
|
3
|
+
export declare function isZodSchema(value: unknown): value is ZodType<unknown>;
|
|
47
4
|
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
5
|
export declare function toOpenApiSchema(schemaOrOpenApi: ZodType | OpenApiSchemaObject | undefined): OpenApiSchemaObject | undefined;
|
|
52
|
-
//# sourceMappingURL=zod-to-openapi.d.ts.map
|