@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,172 @@
|
|
|
1
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if a value is a Zod schema
|
|
4
|
+
* Uses duck typing to detect Zod schemas without requiring the full library
|
|
5
|
+
*/
|
|
6
|
+
export function isZodSchema(value) {
|
|
7
|
+
return (value !== null &&
|
|
8
|
+
typeof value === 'object' &&
|
|
9
|
+
'_def' in value &&
|
|
10
|
+
'safeParse' in value &&
|
|
11
|
+
typeof value.safeParse === 'function');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Convert JSON Schema 7 to OpenAPI 3.0 compatible schema
|
|
15
|
+
*
|
|
16
|
+
* Main differences:
|
|
17
|
+
* - OpenAPI uses `nullable: true` instead of `type: ['string', 'null']`
|
|
18
|
+
* - OpenAPI 3.0 doesn't support `$schema`, `$id`, etc.
|
|
19
|
+
* - Some JSON Schema features need to be simplified
|
|
20
|
+
*/
|
|
21
|
+
function jsonSchemaToOpenApi(jsonSchema) {
|
|
22
|
+
if (typeof jsonSchema === 'boolean') {
|
|
23
|
+
return jsonSchema ? {} : { not: {} };
|
|
24
|
+
}
|
|
25
|
+
const result = {};
|
|
26
|
+
const schema = jsonSchema;
|
|
27
|
+
// Handle type with null (convert to nullable)
|
|
28
|
+
if (Array.isArray(schema.type)) {
|
|
29
|
+
const types = schema.type;
|
|
30
|
+
const nullIndex = types.indexOf('null');
|
|
31
|
+
if (nullIndex !== -1) {
|
|
32
|
+
result.nullable = true;
|
|
33
|
+
const nonNullTypes = types.filter(t => t !== 'null');
|
|
34
|
+
if (nonNullTypes.length === 1) {
|
|
35
|
+
result.type = nonNullTypes[0];
|
|
36
|
+
}
|
|
37
|
+
else if (nonNullTypes.length > 1) {
|
|
38
|
+
// Multiple non-null types - use oneOf
|
|
39
|
+
result.oneOf = nonNullTypes.map(t => ({ type: t }));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (types.length === 1) {
|
|
43
|
+
result.type = types[0];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (schema.type) {
|
|
47
|
+
result.type = schema.type;
|
|
48
|
+
}
|
|
49
|
+
// Copy simple properties
|
|
50
|
+
const simpleProps = [
|
|
51
|
+
'format', 'description', 'default', 'example', 'enum',
|
|
52
|
+
'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum',
|
|
53
|
+
'minLength', 'maxLength', 'pattern',
|
|
54
|
+
'minItems', 'maxItems', 'uniqueItems',
|
|
55
|
+
'minProperties', 'maxProperties',
|
|
56
|
+
'required', 'readOnly', 'writeOnly', 'deprecated',
|
|
57
|
+
];
|
|
58
|
+
for (const prop of simpleProps) {
|
|
59
|
+
if (schema[prop] !== undefined) {
|
|
60
|
+
result[prop] = schema[prop];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Handle items (for arrays)
|
|
64
|
+
if (schema.items) {
|
|
65
|
+
if (Array.isArray(schema.items)) {
|
|
66
|
+
// Tuple - OpenAPI 3.0 doesn't support tuple validation well
|
|
67
|
+
result.items = { oneOf: schema.items.map(jsonSchemaToOpenApi) };
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
result.items = jsonSchemaToOpenApi(schema.items);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Handle properties (for objects)
|
|
74
|
+
if (schema.properties) {
|
|
75
|
+
result.properties = {};
|
|
76
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
77
|
+
result.properties[key] = jsonSchemaToOpenApi(value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Handle additionalProperties
|
|
81
|
+
if (schema.additionalProperties !== undefined) {
|
|
82
|
+
if (typeof schema.additionalProperties === 'boolean') {
|
|
83
|
+
result.additionalProperties = schema.additionalProperties;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
result.additionalProperties = jsonSchemaToOpenApi(schema.additionalProperties);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Handle allOf, oneOf, anyOf
|
|
90
|
+
if (schema.allOf) {
|
|
91
|
+
result.allOf = schema.allOf.map(jsonSchemaToOpenApi);
|
|
92
|
+
}
|
|
93
|
+
if (schema.oneOf) {
|
|
94
|
+
result.oneOf = schema.oneOf.map(jsonSchemaToOpenApi);
|
|
95
|
+
}
|
|
96
|
+
if (schema.anyOf) {
|
|
97
|
+
result.anyOf = schema.anyOf.map(jsonSchemaToOpenApi);
|
|
98
|
+
}
|
|
99
|
+
// Handle not
|
|
100
|
+
if (schema.not) {
|
|
101
|
+
result.not = jsonSchemaToOpenApi(schema.not);
|
|
102
|
+
}
|
|
103
|
+
// Handle const (convert to enum with single value)
|
|
104
|
+
if (schema.const !== undefined) {
|
|
105
|
+
result.enum = [schema.const];
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Convert a Zod schema to an OpenAPI 3.0 schema object
|
|
111
|
+
*
|
|
112
|
+
* Uses `zod-to-json-schema` for the heavy lifting, then converts
|
|
113
|
+
* JSON Schema 7 to OpenAPI 3.0 compatible format.
|
|
114
|
+
*
|
|
115
|
+
* Supports all Zod types including:
|
|
116
|
+
* - Primitives: string, number, boolean, bigint
|
|
117
|
+
* - Complex: object, array, tuple, record
|
|
118
|
+
* - Modifiers: optional, nullable, default
|
|
119
|
+
* - Validators: min, max, email, uuid, url, etc.
|
|
120
|
+
* - Enums: enum, nativeEnum
|
|
121
|
+
* - Unions and intersections
|
|
122
|
+
* - Literals
|
|
123
|
+
* - Effects (transform, refine)
|
|
124
|
+
*
|
|
125
|
+
* @param schema - The Zod schema to convert
|
|
126
|
+
* @returns OpenAPI schema object
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const UserSchema = z.object({
|
|
131
|
+
* id: z.string().uuid(),
|
|
132
|
+
* email: z.string().email(),
|
|
133
|
+
* age: z.number().int().min(0).optional(),
|
|
134
|
+
* });
|
|
135
|
+
*
|
|
136
|
+
* const openApiSchema = zodToOpenApi(UserSchema);
|
|
137
|
+
* // {
|
|
138
|
+
* // type: 'object',
|
|
139
|
+
* // properties: {
|
|
140
|
+
* // id: { type: 'string', format: 'uuid' },
|
|
141
|
+
* // email: { type: 'string', format: 'email' },
|
|
142
|
+
* // age: { type: 'integer', minimum: 0 }
|
|
143
|
+
* // },
|
|
144
|
+
* // required: ['id', 'email']
|
|
145
|
+
* // }
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export function zodToOpenApi(schema) {
|
|
149
|
+
// Convert to JSON Schema using zod-to-json-schema
|
|
150
|
+
const jsonSchema = zodToJsonSchema(schema, {
|
|
151
|
+
target: 'openApi3',
|
|
152
|
+
$refStrategy: 'none', // Inline all references
|
|
153
|
+
});
|
|
154
|
+
// Convert JSON Schema to OpenAPI format
|
|
155
|
+
// The result from zodToJsonSchema may include $schema and definitions
|
|
156
|
+
// which are not part of JsonSchema7Type but are compatible
|
|
157
|
+
return jsonSchemaToOpenApi(jsonSchema);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Convert a Zod schema to OpenAPI schema, or pass through if already an OpenAPI schema
|
|
161
|
+
*/
|
|
162
|
+
export function toOpenApiSchema(schemaOrOpenApi) {
|
|
163
|
+
if (!schemaOrOpenApi) {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
if (isZodSchema(schemaOrOpenApi)) {
|
|
167
|
+
return zodToOpenApi(schemaOrOpenApi);
|
|
168
|
+
}
|
|
169
|
+
// Already an OpenAPI schema object
|
|
170
|
+
return schemaOrOpenApi;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=zod-to-openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-openapi.js","sourceRoot":"","sources":["../../src/openapi/zod-to-openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,eAAe,EACf,mBAAmB,GAEpB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyPluginAsync } from 'fastify';
|
|
2
|
+
import { type FastifySwaggerUiOptions } from '@fastify/swagger-ui';
|
|
3
|
+
import type { SwaggerConfig, OpenApiDocument, OpenApiInfoObject } from '../types.js';
|
|
4
|
+
type Constructor<T = unknown> = new (...args: any[]) => T;
|
|
5
|
+
/**
|
|
6
|
+
* Swagger plugin options
|
|
7
|
+
*/
|
|
8
|
+
export interface SwaggerPluginOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Swagger/OpenAPI configuration
|
|
11
|
+
*/
|
|
12
|
+
config?: SwaggerConfig;
|
|
13
|
+
/**
|
|
14
|
+
* API Info (title, version, description, etc.)
|
|
15
|
+
* Can also be provided via config.info
|
|
16
|
+
*/
|
|
17
|
+
info?: OpenApiInfoObject;
|
|
18
|
+
/**
|
|
19
|
+
* Controllers to document (optional - will auto-discover from registry if not provided)
|
|
20
|
+
*/
|
|
21
|
+
controllers?: Constructor[];
|
|
22
|
+
/**
|
|
23
|
+
* Path to serve the OpenAPI JSON specification
|
|
24
|
+
* @default '/docs/json'
|
|
25
|
+
*/
|
|
26
|
+
jsonPath?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Path to serve the Swagger UI
|
|
29
|
+
* @default '/docs'
|
|
30
|
+
*/
|
|
31
|
+
uiPath?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Whether to expose the Swagger UI
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
exposeUI?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to expose the OpenAPI JSON specification
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
exposeSpec?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Logo configuration for Swagger UI
|
|
44
|
+
*/
|
|
45
|
+
logo?: {
|
|
46
|
+
url: string;
|
|
47
|
+
altText?: string;
|
|
48
|
+
backgroundColor?: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Swagger UI theme
|
|
52
|
+
* @default 'default'
|
|
53
|
+
*/
|
|
54
|
+
theme?: 'default' | 'dark';
|
|
55
|
+
/**
|
|
56
|
+
* Transform the OpenAPI specification before serving
|
|
57
|
+
*/
|
|
58
|
+
transform?: (spec: OpenApiDocument) => OpenApiDocument | Promise<OpenApiDocument>;
|
|
59
|
+
}
|
|
60
|
+
declare module 'fastify' {
|
|
61
|
+
interface FastifyInstance {
|
|
62
|
+
openApiSpec?: OpenApiDocument;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Swagger plugin for Fastify/Rikta
|
|
67
|
+
*
|
|
68
|
+
* Automatically generates OpenAPI documentation from Rikta controllers
|
|
69
|
+
* and serves Swagger UI for interactive API exploration.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { RiktaFactory } from '@riktajs/core';
|
|
74
|
+
* import { swaggerPlugin } from '@riktajs/swagger';
|
|
75
|
+
*
|
|
76
|
+
* const app = await RiktaFactory.create();
|
|
77
|
+
*
|
|
78
|
+
* await app.register(swaggerPlugin, {
|
|
79
|
+
* info: {
|
|
80
|
+
* title: 'My API',
|
|
81
|
+
* version: '1.0.0',
|
|
82
|
+
* description: 'API documentation for My App',
|
|
83
|
+
* },
|
|
84
|
+
* config: {
|
|
85
|
+
* servers: [
|
|
86
|
+
* { url: 'http://localhost:3000', description: 'Development' },
|
|
87
|
+
* ],
|
|
88
|
+
* },
|
|
89
|
+
* });
|
|
90
|
+
*
|
|
91
|
+
* // Swagger UI available at /docs
|
|
92
|
+
* // OpenAPI JSON at /docs/json
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare const swaggerPlugin: FastifyPluginAsync<SwaggerPluginOptions>;
|
|
96
|
+
/**
|
|
97
|
+
* Register swagger plugin with a Rikta application
|
|
98
|
+
*
|
|
99
|
+
* Helper function that provides a simpler API for registering the plugin.
|
|
100
|
+
*
|
|
101
|
+
* @param app - Fastify instance
|
|
102
|
+
* @param options - Swagger plugin options
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import { RiktaFactory } from '@riktajs/core';
|
|
107
|
+
* import { registerSwagger } from '@riktajs/swagger';
|
|
108
|
+
*
|
|
109
|
+
* const app = await RiktaFactory.create();
|
|
110
|
+
*
|
|
111
|
+
* await registerSwagger(app, {
|
|
112
|
+
* info: {
|
|
113
|
+
* title: 'My API',
|
|
114
|
+
* version: '1.0.0',
|
|
115
|
+
* },
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function registerSwagger(app: FastifyInstance, options?: SwaggerPluginOptions): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Create a standalone Swagger configuration for manual use
|
|
122
|
+
*
|
|
123
|
+
* Use this when you need more control over the Swagger setup,
|
|
124
|
+
* or when integrating with an existing Fastify application.
|
|
125
|
+
*
|
|
126
|
+
* @param options - Swagger plugin options
|
|
127
|
+
* @returns Object containing swagger and swaggerUI options and specification
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* import fastify from 'fastify';
|
|
132
|
+
* import fastifySwagger from '@fastify/swagger';
|
|
133
|
+
* import fastifySwaggerUI from '@fastify/swagger-ui';
|
|
134
|
+
* import { createSwaggerConfig } from '@riktajs/swagger';
|
|
135
|
+
*
|
|
136
|
+
* const app = fastify();
|
|
137
|
+
* const { swaggerOptions, swaggerUIOptions, specification } = createSwaggerConfig({
|
|
138
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
139
|
+
* controllers: [UserController, ProductController],
|
|
140
|
+
* });
|
|
141
|
+
*
|
|
142
|
+
* await app.register(fastifySwagger, swaggerOptions);
|
|
143
|
+
* await app.register(fastifySwaggerUI, swaggerUIOptions);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare function createSwaggerConfig(options?: SwaggerPluginOptions): {
|
|
147
|
+
swaggerOptions: {
|
|
148
|
+
mode: 'static';
|
|
149
|
+
specification: {
|
|
150
|
+
document: OpenApiDocument;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
swaggerUIOptions: FastifySwaggerUiOptions;
|
|
154
|
+
specification: OpenApiDocument;
|
|
155
|
+
};
|
|
156
|
+
export {};
|
|
157
|
+
//# sourceMappingURL=swagger.plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swagger.plugin.d.ts","sourceRoot":"","sources":["../../src/plugin/swagger.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGnE,OAAyB,EAAE,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAGrF,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrF,KAAK,WAAW,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IAEvB;;;OAGG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;IAEzB;;OAEG;IACH,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAE5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE;QACL,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAE3B;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACnF;AA4HD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,eAAe;QACvB,WAAW,CAAC,EAAE,eAAe,CAAC;KAC/B;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,aAAa,EAAE,kBAAkB,CAAC,oBAAoB,CAOlE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG;IACvE,cAAc,EAAE;QACd,IAAI,EAAE,QAAQ,CAAC;QACf,aAAa,EAAE;YAAE,QAAQ,EAAE,eAAe,CAAA;SAAE,CAAC;KAC9C,CAAC;IACF,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,aAAa,EAAE,eAAe,CAAC;CAChC,CA+CA"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import fp from 'fastify-plugin';
|
|
2
|
+
import fastifySwagger from '@fastify/swagger';
|
|
3
|
+
import fastifySwaggerUI from '@fastify/swagger-ui';
|
|
4
|
+
import { OpenApiGenerator } from '../openapi/generator.js';
|
|
5
|
+
import { registry } from '@riktajs/core';
|
|
6
|
+
/**
|
|
7
|
+
* Default plugin options
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_OPTIONS = {
|
|
10
|
+
jsonPath: '/docs/json',
|
|
11
|
+
uiPath: '/docs',
|
|
12
|
+
exposeUI: true,
|
|
13
|
+
exposeSpec: true,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Swagger plugin implementation
|
|
17
|
+
*
|
|
18
|
+
* Registers @fastify/swagger and @fastify/swagger-ui with automatic
|
|
19
|
+
* OpenAPI specification generation from Rikta controllers.
|
|
20
|
+
*/
|
|
21
|
+
async function swaggerPluginImpl(fastify, options) {
|
|
22
|
+
const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
23
|
+
const { jsonPath, uiPath, exposeUI, exposeSpec, controllers, config, info, transform } = mergedOptions;
|
|
24
|
+
// Build info object from options or config
|
|
25
|
+
const apiInfo = info || config?.info || {
|
|
26
|
+
title: 'API Documentation',
|
|
27
|
+
version: '1.0.0',
|
|
28
|
+
};
|
|
29
|
+
// Create OpenAPI generator
|
|
30
|
+
const generator = new OpenApiGenerator({
|
|
31
|
+
...config,
|
|
32
|
+
info: apiInfo,
|
|
33
|
+
});
|
|
34
|
+
// Get controllers to document
|
|
35
|
+
const controllersToDocument = controllers || registry.getControllers();
|
|
36
|
+
// Add controllers to generator
|
|
37
|
+
for (const controller of controllersToDocument) {
|
|
38
|
+
generator.addController(controller);
|
|
39
|
+
}
|
|
40
|
+
// Add security schemes from config
|
|
41
|
+
if (config?.securitySchemes) {
|
|
42
|
+
for (const [name, scheme] of Object.entries(config.securitySchemes)) {
|
|
43
|
+
generator.addSecurityScheme(name, scheme);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Generate OpenAPI specification
|
|
47
|
+
let spec = generator.generate();
|
|
48
|
+
// Apply transform if provided
|
|
49
|
+
if (transform) {
|
|
50
|
+
spec = await transform(spec);
|
|
51
|
+
}
|
|
52
|
+
// Register @fastify/swagger with static specification
|
|
53
|
+
await fastify.register(fastifySwagger, {
|
|
54
|
+
mode: 'static',
|
|
55
|
+
specification: {
|
|
56
|
+
document: spec, // Type assertion needed due to fastify-swagger types
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
// Register @fastify/swagger-ui if enabled
|
|
60
|
+
if (exposeUI) {
|
|
61
|
+
const uiOptions = {
|
|
62
|
+
routePrefix: uiPath,
|
|
63
|
+
uiConfig: {
|
|
64
|
+
docExpansion: 'list',
|
|
65
|
+
deepLinking: true,
|
|
66
|
+
displayRequestDuration: true,
|
|
67
|
+
filter: true,
|
|
68
|
+
syntaxHighlight: {
|
|
69
|
+
activate: true,
|
|
70
|
+
theme: mergedOptions.theme === 'dark' ? 'monokai' : 'agate',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
staticCSP: true,
|
|
74
|
+
transformStaticCSP: (header) => header,
|
|
75
|
+
};
|
|
76
|
+
// Add logo if provided
|
|
77
|
+
if (mergedOptions.logo) {
|
|
78
|
+
uiOptions.logo = {
|
|
79
|
+
type: 'image/png',
|
|
80
|
+
content: mergedOptions.logo.url,
|
|
81
|
+
href: mergedOptions.logo.url,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
await fastify.register(fastifySwaggerUI, uiOptions);
|
|
85
|
+
}
|
|
86
|
+
// Add JSON spec route if enabled
|
|
87
|
+
// @fastify/swagger-ui registers routes at {uiPath}/json when UI is enabled
|
|
88
|
+
// So we only add custom route if:
|
|
89
|
+
// 1. UI is disabled (no swagger-ui default route exists)
|
|
90
|
+
// 2. jsonPath differs from swagger-ui default path
|
|
91
|
+
const defaultSwaggerUIJsonPath = `${uiPath}/json`;
|
|
92
|
+
const shouldRegisterCustomJsonRoute = exposeSpec && (!exposeUI ||
|
|
93
|
+
(jsonPath !== defaultSwaggerUIJsonPath && jsonPath !== '/docs/json'));
|
|
94
|
+
if (shouldRegisterCustomJsonRoute) {
|
|
95
|
+
fastify.get(jsonPath, {
|
|
96
|
+
schema: {
|
|
97
|
+
hide: true,
|
|
98
|
+
},
|
|
99
|
+
}, async () => {
|
|
100
|
+
return spec;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// Store spec on fastify instance for later access
|
|
104
|
+
fastify.decorate('openApiSpec', spec);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Swagger plugin for Fastify/Rikta
|
|
108
|
+
*
|
|
109
|
+
* Automatically generates OpenAPI documentation from Rikta controllers
|
|
110
|
+
* and serves Swagger UI for interactive API exploration.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* import { RiktaFactory } from '@riktajs/core';
|
|
115
|
+
* import { swaggerPlugin } from '@riktajs/swagger';
|
|
116
|
+
*
|
|
117
|
+
* const app = await RiktaFactory.create();
|
|
118
|
+
*
|
|
119
|
+
* await app.register(swaggerPlugin, {
|
|
120
|
+
* info: {
|
|
121
|
+
* title: 'My API',
|
|
122
|
+
* version: '1.0.0',
|
|
123
|
+
* description: 'API documentation for My App',
|
|
124
|
+
* },
|
|
125
|
+
* config: {
|
|
126
|
+
* servers: [
|
|
127
|
+
* { url: 'http://localhost:3000', description: 'Development' },
|
|
128
|
+
* ],
|
|
129
|
+
* },
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* // Swagger UI available at /docs
|
|
133
|
+
* // OpenAPI JSON at /docs/json
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export const swaggerPlugin = fp(swaggerPluginImpl, {
|
|
137
|
+
fastify: '>=4.0.0',
|
|
138
|
+
name: '@riktajs/swagger',
|
|
139
|
+
dependencies: [],
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* Register swagger plugin with a Rikta application
|
|
143
|
+
*
|
|
144
|
+
* Helper function that provides a simpler API for registering the plugin.
|
|
145
|
+
*
|
|
146
|
+
* @param app - Fastify instance
|
|
147
|
+
* @param options - Swagger plugin options
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* import { RiktaFactory } from '@riktajs/core';
|
|
152
|
+
* import { registerSwagger } from '@riktajs/swagger';
|
|
153
|
+
*
|
|
154
|
+
* const app = await RiktaFactory.create();
|
|
155
|
+
*
|
|
156
|
+
* await registerSwagger(app, {
|
|
157
|
+
* info: {
|
|
158
|
+
* title: 'My API',
|
|
159
|
+
* version: '1.0.0',
|
|
160
|
+
* },
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export async function registerSwagger(app, options = {}) {
|
|
165
|
+
await app.register(swaggerPlugin, options);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create a standalone Swagger configuration for manual use
|
|
169
|
+
*
|
|
170
|
+
* Use this when you need more control over the Swagger setup,
|
|
171
|
+
* or when integrating with an existing Fastify application.
|
|
172
|
+
*
|
|
173
|
+
* @param options - Swagger plugin options
|
|
174
|
+
* @returns Object containing swagger and swaggerUI options and specification
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```typescript
|
|
178
|
+
* import fastify from 'fastify';
|
|
179
|
+
* import fastifySwagger from '@fastify/swagger';
|
|
180
|
+
* import fastifySwaggerUI from '@fastify/swagger-ui';
|
|
181
|
+
* import { createSwaggerConfig } from '@riktajs/swagger';
|
|
182
|
+
*
|
|
183
|
+
* const app = fastify();
|
|
184
|
+
* const { swaggerOptions, swaggerUIOptions, specification } = createSwaggerConfig({
|
|
185
|
+
* info: { title: 'My API', version: '1.0.0' },
|
|
186
|
+
* controllers: [UserController, ProductController],
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* await app.register(fastifySwagger, swaggerOptions);
|
|
190
|
+
* await app.register(fastifySwaggerUI, swaggerUIOptions);
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export function createSwaggerConfig(options = {}) {
|
|
194
|
+
const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
195
|
+
const { uiPath, controllers, config, info } = mergedOptions;
|
|
196
|
+
// Build info object
|
|
197
|
+
const apiInfo = info || config?.info || {
|
|
198
|
+
title: 'API Documentation',
|
|
199
|
+
version: '1.0.0',
|
|
200
|
+
};
|
|
201
|
+
// Create generator
|
|
202
|
+
const generator = new OpenApiGenerator({
|
|
203
|
+
...config,
|
|
204
|
+
info: apiInfo,
|
|
205
|
+
});
|
|
206
|
+
// Add controllers
|
|
207
|
+
const controllersToDocument = controllers || registry.getControllers();
|
|
208
|
+
for (const controller of controllersToDocument) {
|
|
209
|
+
generator.addController(controller);
|
|
210
|
+
}
|
|
211
|
+
// Add security schemes
|
|
212
|
+
if (config?.securitySchemes) {
|
|
213
|
+
for (const [name, scheme] of Object.entries(config.securitySchemes)) {
|
|
214
|
+
generator.addSecurityScheme(name, scheme);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const specification = generator.generate();
|
|
218
|
+
return {
|
|
219
|
+
swaggerOptions: {
|
|
220
|
+
mode: 'static',
|
|
221
|
+
specification: { document: specification },
|
|
222
|
+
},
|
|
223
|
+
swaggerUIOptions: {
|
|
224
|
+
routePrefix: uiPath,
|
|
225
|
+
uiConfig: {
|
|
226
|
+
docExpansion: 'list',
|
|
227
|
+
deepLinking: true,
|
|
228
|
+
displayRequestDuration: true,
|
|
229
|
+
filter: true,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
specification,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=swagger.plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swagger.plugin.js","sourceRoot":"","sources":["../../src/plugin/swagger.plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChC,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,gBAAkD,MAAM,qBAAqB,CAAC;AAErF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuEzC;;GAEG;AACH,MAAM,eAAe,GAA4F;IAC/G,QAAQ,EAAE,YAAY;IACtB,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;;GAKG;AACH,KAAK,UAAU,iBAAiB,CAC9B,OAAwB,EACxB,OAA6B;IAE7B,MAAM,aAAa,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;IACzD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC;IAEvG,2CAA2C;IAC3C,MAAM,OAAO,GAAsB,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI;QACzD,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO;KACjB,CAAC;IAEF,2BAA2B;IAC3B,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC;QACrC,GAAG,MAAM;QACT,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,8BAA8B;IAC9B,MAAM,qBAAqB,GAAG,WAAW,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;IAEvE,+BAA+B;IAC/B,KAAK,MAAM,UAAU,IAAI,qBAAqB,EAAE,CAAC;QAC/C,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,mCAAmC;IACnC,IAAI,MAAM,EAAE,eAAe,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;YACpE,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAEhC,8BAA8B;IAC9B,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,sDAAsD;IACtD,MAAM,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE;QACrC,IAAI,EAAE,QAAQ;QACd,aAAa,EAAE;YACb,QAAQ,EAAE,IAAa,EAAE,qDAAqD;SAC/E;KACF,CAAC,CAAC;IAEH,0CAA0C;IAC1C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,SAAS,GAA4B;YACzC,WAAW,EAAE,MAAM;YACnB,QAAQ,EAAE;gBACR,YAAY,EAAE,MAAM;gBACpB,WAAW,EAAE,IAAI;gBACjB,sBAAsB,EAAE,IAAI;gBAC5B,MAAM,EAAE,IAAI;gBACZ,eAAe,EAAE;oBACf,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,aAAa,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;iBAC5D;aACF;YACD,SAAS,EAAE,IAAI;YACf,kBAAkB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM;SACvC,CAAC;QAEF,uBAAuB;QACvB,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;YACvB,SAAS,CAAC,IAAI,GAAG;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG;gBAC/B,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG;aAC7B,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,CAAC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC;IAED,iCAAiC;IACjC,2EAA2E;IAC3E,kCAAkC;IAClC,yDAAyD;IACzD,mDAAmD;IACnD,MAAM,wBAAwB,GAAG,GAAG,MAAM,OAAO,CAAC;IAClD,MAAM,6BAA6B,GAAG,UAAU,IAAI,CAClD,CAAC,QAAQ;QACT,CAAC,QAAQ,KAAK,wBAAwB,IAAI,QAAQ,KAAK,YAAY,CAAC,CACrE,CAAC;IAEF,IAAI,6BAA6B,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACpB,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI;aACX;SACF,EAAE,KAAK,IAAI,EAAE;YACZ,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAED,kDAAkD;IAClD,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,aAAa,GAA6C,EAAE,CACvE,iBAAiB,EACjB;IACE,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,kBAAkB;IACxB,YAAY,EAAE,EAAE;CACjB,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAoB,EACpB,UAAgC,EAAE;IAElC,MAAM,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAgC,EAAE;IAQpE,MAAM,aAAa,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;IACzD,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC;IAE5D,oBAAoB;IACpB,MAAM,OAAO,GAAsB,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI;QACzD,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO;KACjB,CAAC;IAEF,mBAAmB;IACnB,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC;QACrC,GAAG,MAAM;QACT,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,kBAAkB;IAClB,MAAM,qBAAqB,GAAG,WAAW,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;IACvE,KAAK,MAAM,UAAU,IAAI,qBAAqB,EAAE,CAAC;QAC/C,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,uBAAuB;IACvB,IAAI,MAAM,EAAE,eAAe,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;YACpE,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAE3C,OAAO;QACL,cAAc,EAAE;YACd,IAAI,EAAE,QAAQ;YACd,aAAa,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE;SAC3C;QACD,gBAAgB,EAAE;YAChB,WAAW,EAAE,MAAM;YACnB,QAAQ,EAAE;gBACR,YAAY,EAAE,MAAM;gBACpB,WAAW,EAAE,IAAI;gBACjB,sBAAsB,EAAE,IAAI;gBAC5B,MAAM,EAAE,IAAI;aACb;SACF;QACD,aAAa;KACd,CAAC;AACJ,CAAC"}
|