@morojs/moro 1.0.0 → 1.0.1
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 +1 -1
- package/dist/core/config/index.d.ts +5 -5
- package/dist/core/config/index.js +1 -1
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +1 -1
- package/dist/core/config/loader.js +58 -82
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/schema.d.ts +1 -1
- package/dist/core/config/schema.js +52 -111
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +2 -2
- package/dist/core/config/utils.js +18 -18
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/database/adapters/drizzle.d.ts +1 -1
- package/dist/core/database/adapters/drizzle.js +39 -55
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/index.d.ts +7 -7
- package/dist/core/database/adapters/index.js +11 -11
- package/dist/core/database/adapters/index.js.map +1 -1
- package/dist/core/database/adapters/mongodb.d.ts +1 -1
- package/dist/core/database/adapters/mongodb.js +19 -23
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +1 -1
- package/dist/core/database/adapters/mysql.js +31 -27
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +1 -1
- package/dist/core/database/adapters/postgresql.js +27 -35
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +1 -1
- package/dist/core/database/adapters/redis.js +24 -24
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sqlite.d.ts +1 -1
- package/dist/core/database/adapters/sqlite.js +36 -36
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/docs/index.d.ts +7 -7
- package/dist/core/docs/index.js +13 -15
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.d.ts +5 -5
- package/dist/core/docs/openapi-generator.js +93 -94
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/simple-docs.d.ts +1 -1
- package/dist/core/docs/simple-docs.js +25 -28
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.d.ts +2 -2
- package/dist/core/docs/swagger-ui.js +46 -51
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.d.ts +1 -1
- package/dist/core/docs/zod-to-openapi.js +115 -125
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.js +15 -21
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/events/index.d.ts +2 -2
- package/dist/core/framework.d.ts +5 -5
- package/dist/core/framework.js +55 -60
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +2 -2
- package/dist/core/http/http-server.js +228 -261
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/index.d.ts +3 -3
- package/dist/core/http/router.d.ts +1 -1
- package/dist/core/http/router.js +15 -17
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.d.ts +1 -1
- package/dist/core/logger/filters.js +16 -16
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +3 -3
- package/dist/core/logger/logger.d.ts +1 -1
- package/dist/core/logger/logger.js +48 -59
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.d.ts +4 -4
- package/dist/core/logger/outputs.js +16 -20
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.js +19 -19
- package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cache/index.js +3 -3
- package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.js +5 -5
- package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.js +18 -18
- package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.js +8 -8
- package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +14 -14
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +13 -15
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cdn/index.js +3 -3
- package/dist/core/middleware/built-in/adapters/index.d.ts +4 -4
- package/dist/core/middleware/built-in/auth.d.ts +1 -1
- package/dist/core/middleware/built-in/auth.js +14 -14
- package/dist/core/middleware/built-in/cache.d.ts +2 -2
- package/dist/core/middleware/built-in/cache.js +43 -45
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/cdn.d.ts +2 -2
- package/dist/core/middleware/built-in/cdn.js +27 -29
- package/dist/core/middleware/built-in/cdn.js.map +1 -1
- package/dist/core/middleware/built-in/cookie.d.ts +2 -2
- package/dist/core/middleware/built-in/cookie.js +17 -17
- package/dist/core/middleware/built-in/cookie.js.map +1 -1
- package/dist/core/middleware/built-in/cors.d.ts +1 -1
- package/dist/core/middleware/built-in/cors.js +13 -13
- package/dist/core/middleware/built-in/csp.d.ts +1 -1
- package/dist/core/middleware/built-in/csp.js +22 -25
- package/dist/core/middleware/built-in/csp.js.map +1 -1
- package/dist/core/middleware/built-in/csrf.d.ts +1 -1
- package/dist/core/middleware/built-in/csrf.js +21 -24
- package/dist/core/middleware/built-in/csrf.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker.js +2 -2
- package/dist/core/middleware/built-in/index.d.ts +14 -14
- package/dist/core/middleware/built-in/performance-monitor.js +2 -2
- package/dist/core/middleware/built-in/rate-limit.d.ts +1 -1
- package/dist/core/middleware/built-in/rate-limit.js +12 -12
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/session.d.ts +5 -5
- package/dist/core/middleware/built-in/session.js +35 -38
- package/dist/core/middleware/built-in/session.js.map +1 -1
- package/dist/core/middleware/built-in/sse.d.ts +1 -1
- package/dist/core/middleware/built-in/sse.js +20 -22
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/middleware/built-in/validation.d.ts +1 -1
- package/dist/core/middleware/built-in/validation.js +13 -13
- package/dist/core/middleware/index.d.ts +5 -5
- package/dist/core/middleware/index.js +16 -16
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +2 -2
- package/dist/core/modules/auto-discovery.js +12 -13
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/index.d.ts +2 -2
- package/dist/core/modules/index.js.map +1 -1
- package/dist/core/modules/modules.d.ts +3 -3
- package/dist/core/modules/modules.js +3 -6
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/index.d.ts +2 -2
- package/dist/core/networking/index.js.map +1 -1
- package/dist/core/networking/service-discovery.d.ts +2 -2
- package/dist/core/networking/service-discovery.js +27 -27
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/networking/websocket-manager.d.ts +3 -3
- package/dist/core/networking/websocket-manager.js +15 -16
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/app-integration.d.ts +2 -2
- package/dist/core/routing/app-integration.js +13 -13
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +3 -3
- package/dist/core/routing/index.js +43 -52
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/aws-lambda-adapter.d.ts +3 -3
- package/dist/core/runtime/aws-lambda-adapter.js +14 -16
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
- package/dist/core/runtime/base-adapter.d.ts +2 -2
- package/dist/core/runtime/base-adapter.js +11 -12
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.d.ts +3 -3
- package/dist/core/runtime/cloudflare-workers-adapter.js +20 -21
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/index.d.ts +9 -9
- package/dist/core/runtime/index.js +4 -4
- package/dist/core/runtime/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.d.ts +5 -5
- package/dist/core/runtime/node-adapter.js +35 -35
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.d.ts +3 -3
- package/dist/core/runtime/vercel-edge-adapter.js +12 -15
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.js +6 -6
- package/dist/core/utilities/container.d.ts +1 -1
- package/dist/core/utilities/container.js +17 -22
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +3 -3
- package/dist/core/utilities/hooks.js +11 -11
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/utilities/index.d.ts +4 -4
- package/dist/core/validation/index.d.ts +3 -3
- package/dist/core/validation/index.js +15 -15
- package/dist/core/validation/index.js.map +1 -1
- package/dist/index.d.ts +31 -30
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +14 -14
- package/dist/moro.js +79 -88
- package/dist/moro.js.map +1 -1
- package/dist/types/cache.d.ts +1 -1
- package/dist/types/core.d.ts +2 -2
- package/dist/types/events.d.ts +19 -19
- package/dist/types/hooks.d.ts +1 -1
- package/dist/types/http.d.ts +2 -2
- package/dist/types/logger.d.ts +3 -3
- package/dist/types/module.d.ts +2 -2
- package/dist/types/runtime.d.ts +2 -2
- package/dist/types/session.d.ts +4 -4
- package/package.json +180 -164
- package/src/core/config/index.ts +7 -9
- package/src/core/config/loader.ts +86 -158
- package/src/core/config/schema.ts +59 -122
- package/src/core/config/utils.ts +27 -45
- package/src/core/database/adapters/drizzle.ts +53 -75
- package/src/core/database/adapters/index.ts +26 -29
- package/src/core/database/adapters/mongodb.ts +31 -54
- package/src/core/database/adapters/mysql.ts +40 -50
- package/src/core/database/adapters/postgresql.ts +32 -42
- package/src/core/database/adapters/redis.ts +31 -36
- package/src/core/database/adapters/sqlite.ts +43 -51
- package/src/core/database/index.ts +2 -2
- package/src/core/docs/index.ts +25 -39
- package/src/core/docs/openapi-generator.ts +104 -117
- package/src/core/docs/simple-docs.ts +29 -39
- package/src/core/docs/swagger-ui.ts +57 -76
- package/src/core/docs/zod-to-openapi.ts +121 -153
- package/src/core/events/event-bus.ts +22 -45
- package/src/core/events/index.ts +2 -2
- package/src/core/framework.ts +119 -197
- package/src/core/http/http-server.ts +260 -360
- package/src/core/http/index.ts +3 -8
- package/src/core/http/router.ts +19 -31
- package/src/core/logger/filters.ts +19 -22
- package/src/core/logger/index.ts +3 -3
- package/src/core/logger/logger.ts +59 -100
- package/src/core/logger/outputs.ts +23 -27
- package/src/core/middleware/built-in/adapters/cache/file.ts +21 -23
- package/src/core/middleware/built-in/adapters/cache/index.ts +11 -14
- package/src/core/middleware/built-in/adapters/cache/memory.ts +7 -7
- package/src/core/middleware/built-in/adapters/cache/redis.ts +21 -24
- package/src/core/middleware/built-in/adapters/cdn/azure.ts +10 -18
- package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +19 -36
- package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +17 -26
- package/src/core/middleware/built-in/adapters/cdn/index.ts +10 -10
- package/src/core/middleware/built-in/adapters/index.ts +4 -4
- package/src/core/middleware/built-in/auth.ts +16 -16
- package/src/core/middleware/built-in/cache.ts +50 -67
- package/src/core/middleware/built-in/cdn.ts +34 -61
- package/src/core/middleware/built-in/cookie.ts +23 -28
- package/src/core/middleware/built-in/cors.ts +17 -17
- package/src/core/middleware/built-in/csp.ts +25 -31
- package/src/core/middleware/built-in/csrf.ts +24 -29
- package/src/core/middleware/built-in/error-tracker.ts +3 -3
- package/src/core/middleware/built-in/index.ts +28 -28
- package/src/core/middleware/built-in/performance-monitor.ts +4 -4
- package/src/core/middleware/built-in/rate-limit.ts +15 -15
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/session.ts +47 -70
- package/src/core/middleware/built-in/sse.ts +23 -28
- package/src/core/middleware/built-in/validation.ts +15 -15
- package/src/core/middleware/index.ts +26 -37
- package/src/core/modules/auto-discovery.ts +21 -31
- package/src/core/modules/index.ts +2 -5
- package/src/core/modules/modules.ts +11 -20
- package/src/core/networking/index.ts +2 -6
- package/src/core/networking/service-discovery.ts +41 -61
- package/src/core/networking/websocket-manager.ts +27 -36
- package/src/core/routing/app-integration.ts +19 -32
- package/src/core/routing/index.ts +57 -88
- package/src/core/runtime/aws-lambda-adapter.ts +20 -30
- package/src/core/runtime/base-adapter.ts +17 -27
- package/src/core/runtime/cloudflare-workers-adapter.ts +28 -42
- package/src/core/runtime/index.ts +21 -33
- package/src/core/runtime/node-adapter.ts +59 -73
- package/src/core/runtime/vercel-edge-adapter.ts +18 -29
- package/src/core/utilities/circuit-breaker.ts +7 -7
- package/src/core/utilities/container.ts +52 -89
- package/src/core/utilities/hooks.ts +17 -23
- package/src/core/utilities/index.ts +4 -4
- package/src/core/validation/index.ts +25 -51
- package/src/index.ts +58 -60
- package/src/moro.ts +119 -191
- package/src/types/cache.ts +1 -1
- package/src/types/core.ts +2 -2
- package/src/types/database.ts +2 -10
- package/src/types/events.ts +23 -31
- package/src/types/hooks.ts +1 -1
- package/src/types/http.ts +5 -8
- package/src/types/logger.ts +7 -23
- package/src/types/module.ts +2 -2
- package/src/types/runtime.ts +6 -21
- package/src/types/session.ts +4 -4
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
// OpenAPI Specification Generator for Moro Framework
|
|
2
2
|
// Extracts route information from intelligent routing and generates OpenAPI 3.0 specs
|
|
3
3
|
|
|
4
|
-
import { CompiledRoute, RouteSchema } from
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
generateExampleFromSchema,
|
|
8
|
-
OpenAPISchema,
|
|
9
|
-
} from "./zod-to-openapi";
|
|
10
|
-
import { createFrameworkLogger } from "../logger";
|
|
4
|
+
import { CompiledRoute, RouteSchema } from '../routing';
|
|
5
|
+
import { zodToOpenAPI, generateExampleFromSchema, OpenAPISchema } from './zod-to-openapi';
|
|
6
|
+
import { createFrameworkLogger } from '../logger';
|
|
11
7
|
|
|
12
|
-
const logger = createFrameworkLogger(
|
|
8
|
+
const logger = createFrameworkLogger('OpenAPIGenerator');
|
|
13
9
|
|
|
14
10
|
// OpenAPI 3.0 specification structure
|
|
15
11
|
export interface OpenAPISpec {
|
|
@@ -57,7 +53,7 @@ export interface OpenAPIOperation {
|
|
|
57
53
|
|
|
58
54
|
export interface OpenAPIParameter {
|
|
59
55
|
name: string;
|
|
60
|
-
in:
|
|
56
|
+
in: 'query' | 'path' | 'header' | 'cookie';
|
|
61
57
|
required?: boolean;
|
|
62
58
|
description?: string;
|
|
63
59
|
schema: OpenAPISchema;
|
|
@@ -102,10 +98,10 @@ export interface OpenAPIComponents {
|
|
|
102
98
|
}
|
|
103
99
|
|
|
104
100
|
export interface OpenAPISecurityScheme {
|
|
105
|
-
type:
|
|
101
|
+
type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
|
|
106
102
|
description?: string;
|
|
107
103
|
name?: string;
|
|
108
|
-
in?:
|
|
104
|
+
in?: 'query' | 'header' | 'cookie';
|
|
109
105
|
scheme?: string;
|
|
110
106
|
bearerFormat?: string;
|
|
111
107
|
}
|
|
@@ -136,7 +132,7 @@ export class OpenAPIGenerator {
|
|
|
136
132
|
private tags = new Set<string>();
|
|
137
133
|
|
|
138
134
|
constructor(private options: GenerationOptions) {
|
|
139
|
-
logger.debug(
|
|
135
|
+
logger.debug('OpenAPI Generator initialized', 'Initialization', {
|
|
140
136
|
includeExamples: options.includeExamples,
|
|
141
137
|
includeSchemas: options.includeSchemas,
|
|
142
138
|
});
|
|
@@ -147,34 +143,30 @@ export class OpenAPIGenerator {
|
|
|
147
143
|
this.routes.push(...routes);
|
|
148
144
|
|
|
149
145
|
// Extract tags from routes
|
|
150
|
-
routes.forEach(
|
|
146
|
+
routes.forEach(route => {
|
|
151
147
|
if (route.schema.tags) {
|
|
152
|
-
route.schema.tags.forEach(
|
|
148
|
+
route.schema.tags.forEach(tag => this.tags.add(tag));
|
|
153
149
|
}
|
|
154
150
|
});
|
|
155
151
|
|
|
156
|
-
logger.debug(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
totalRoutes: this.routes.length,
|
|
161
|
-
uniqueTags: this.tags.size,
|
|
162
|
-
},
|
|
163
|
-
);
|
|
152
|
+
logger.debug(`Added ${routes.length} routes to documentation`, 'RouteAddition', {
|
|
153
|
+
totalRoutes: this.routes.length,
|
|
154
|
+
uniqueTags: this.tags.size,
|
|
155
|
+
});
|
|
164
156
|
}
|
|
165
157
|
|
|
166
158
|
// Generate complete OpenAPI specification
|
|
167
159
|
generate(): OpenAPISpec {
|
|
168
|
-
logger.info(
|
|
160
|
+
logger.info('Generating OpenAPI specification', 'Generation', {
|
|
169
161
|
routeCount: this.routes.length,
|
|
170
162
|
tagCount: this.tags.size,
|
|
171
163
|
});
|
|
172
164
|
|
|
173
165
|
const spec: OpenAPISpec = {
|
|
174
|
-
openapi:
|
|
166
|
+
openapi: '3.0.3',
|
|
175
167
|
info: this.options.info,
|
|
176
168
|
servers: this.options.servers || [
|
|
177
|
-
{ url:
|
|
169
|
+
{ url: 'http://localhost:3000', description: 'Development server' },
|
|
178
170
|
],
|
|
179
171
|
paths: this.generatePaths(),
|
|
180
172
|
tags: this.generateTags(),
|
|
@@ -188,7 +180,7 @@ export class OpenAPIGenerator {
|
|
|
188
180
|
};
|
|
189
181
|
}
|
|
190
182
|
|
|
191
|
-
logger.info(
|
|
183
|
+
logger.info('OpenAPI specification generated successfully', 'Generation', {
|
|
192
184
|
pathCount: Object.keys(spec.paths).length,
|
|
193
185
|
schemaCount: this.schemas.size,
|
|
194
186
|
tagCount: spec.tags?.length || 0,
|
|
@@ -231,10 +223,7 @@ export class OpenAPIGenerator {
|
|
|
231
223
|
}
|
|
232
224
|
|
|
233
225
|
// Add request body (for POST, PUT, PATCH)
|
|
234
|
-
if (
|
|
235
|
-
["POST", "PUT", "PATCH"].includes(route.method) &&
|
|
236
|
-
route.validation?.body
|
|
237
|
-
) {
|
|
226
|
+
if (['POST', 'PUT', 'PATCH'].includes(route.method) && route.validation?.body) {
|
|
238
227
|
operation.requestBody = this.generateRequestBody(route);
|
|
239
228
|
}
|
|
240
229
|
|
|
@@ -257,7 +246,7 @@ export class OpenAPIGenerator {
|
|
|
257
246
|
for (const [name, schema] of Object.entries(paramSchema.properties)) {
|
|
258
247
|
parameters.push({
|
|
259
248
|
name,
|
|
260
|
-
in:
|
|
249
|
+
in: 'path',
|
|
261
250
|
required: true,
|
|
262
251
|
schema,
|
|
263
252
|
description: schema.description,
|
|
@@ -275,7 +264,7 @@ export class OpenAPIGenerator {
|
|
|
275
264
|
const isRequired = querySchema.required?.includes(name) || false;
|
|
276
265
|
parameters.push({
|
|
277
266
|
name,
|
|
278
|
-
in:
|
|
267
|
+
in: 'query',
|
|
279
268
|
required: isRequired,
|
|
280
269
|
schema,
|
|
281
270
|
description: schema.description,
|
|
@@ -293,7 +282,7 @@ export class OpenAPIGenerator {
|
|
|
293
282
|
const isRequired = headerSchema.required?.includes(name) || false;
|
|
294
283
|
parameters.push({
|
|
295
284
|
name,
|
|
296
|
-
in:
|
|
285
|
+
in: 'header',
|
|
297
286
|
required: isRequired,
|
|
298
287
|
schema,
|
|
299
288
|
description: schema.description,
|
|
@@ -310,11 +299,11 @@ export class OpenAPIGenerator {
|
|
|
310
299
|
private generateRequestBody(route: RouteSchema): OpenAPIRequestBody {
|
|
311
300
|
if (!route.validation?.body) {
|
|
312
301
|
return {
|
|
313
|
-
description:
|
|
302
|
+
description: 'Request body',
|
|
314
303
|
required: true,
|
|
315
304
|
content: {
|
|
316
|
-
|
|
317
|
-
schema: { type:
|
|
305
|
+
'application/json': {
|
|
306
|
+
schema: { type: 'object' },
|
|
318
307
|
},
|
|
319
308
|
},
|
|
320
309
|
};
|
|
@@ -326,10 +315,10 @@ export class OpenAPIGenerator {
|
|
|
326
315
|
: undefined;
|
|
327
316
|
|
|
328
317
|
return {
|
|
329
|
-
description:
|
|
318
|
+
description: 'Request body',
|
|
330
319
|
required: true,
|
|
331
320
|
content: {
|
|
332
|
-
|
|
321
|
+
'application/json': {
|
|
333
322
|
schema: bodySchema,
|
|
334
323
|
example,
|
|
335
324
|
},
|
|
@@ -338,22 +327,20 @@ export class OpenAPIGenerator {
|
|
|
338
327
|
}
|
|
339
328
|
|
|
340
329
|
// Generate responses
|
|
341
|
-
private generateResponses(
|
|
342
|
-
route: RouteSchema,
|
|
343
|
-
): Record<string, OpenAPIResponse> {
|
|
330
|
+
private generateResponses(route: RouteSchema): Record<string, OpenAPIResponse> {
|
|
344
331
|
const responses: Record<string, OpenAPIResponse> = {};
|
|
345
332
|
|
|
346
333
|
// Success response
|
|
347
|
-
responses[
|
|
348
|
-
description:
|
|
334
|
+
responses['200'] = {
|
|
335
|
+
description: 'Successful response',
|
|
349
336
|
content: {
|
|
350
|
-
|
|
337
|
+
'application/json': {
|
|
351
338
|
schema: {
|
|
352
|
-
type:
|
|
339
|
+
type: 'object',
|
|
353
340
|
properties: {
|
|
354
|
-
success: { type:
|
|
355
|
-
data: { type:
|
|
356
|
-
message: { type:
|
|
341
|
+
success: { type: 'boolean', example: true },
|
|
342
|
+
data: { type: 'object', description: 'Response data' },
|
|
343
|
+
message: { type: 'string', example: 'Operation successful' },
|
|
357
344
|
},
|
|
358
345
|
},
|
|
359
346
|
},
|
|
@@ -361,19 +348,19 @@ export class OpenAPIGenerator {
|
|
|
361
348
|
};
|
|
362
349
|
|
|
363
350
|
// Add 201 for POST requests
|
|
364
|
-
if (route.method ===
|
|
365
|
-
responses[
|
|
366
|
-
description:
|
|
351
|
+
if (route.method === 'POST') {
|
|
352
|
+
responses['201'] = {
|
|
353
|
+
description: 'Resource created successfully',
|
|
367
354
|
content: {
|
|
368
|
-
|
|
355
|
+
'application/json': {
|
|
369
356
|
schema: {
|
|
370
|
-
type:
|
|
357
|
+
type: 'object',
|
|
371
358
|
properties: {
|
|
372
|
-
success: { type:
|
|
373
|
-
data: { type:
|
|
359
|
+
success: { type: 'boolean', example: true },
|
|
360
|
+
data: { type: 'object', description: 'Created resource' },
|
|
374
361
|
message: {
|
|
375
|
-
type:
|
|
376
|
-
example:
|
|
362
|
+
type: 'string',
|
|
363
|
+
example: 'Resource created successfully',
|
|
377
364
|
},
|
|
378
365
|
},
|
|
379
366
|
},
|
|
@@ -384,30 +371,30 @@ export class OpenAPIGenerator {
|
|
|
384
371
|
|
|
385
372
|
// Validation error response
|
|
386
373
|
if (route.validation) {
|
|
387
|
-
responses[
|
|
388
|
-
description:
|
|
374
|
+
responses['400'] = {
|
|
375
|
+
description: 'Validation error',
|
|
389
376
|
content: {
|
|
390
|
-
|
|
377
|
+
'application/json': {
|
|
391
378
|
schema: {
|
|
392
|
-
type:
|
|
379
|
+
type: 'object',
|
|
393
380
|
properties: {
|
|
394
|
-
success: { type:
|
|
395
|
-
error: { type:
|
|
381
|
+
success: { type: 'boolean', example: false },
|
|
382
|
+
error: { type: 'string', example: 'Validation failed' },
|
|
396
383
|
details: {
|
|
397
|
-
type:
|
|
384
|
+
type: 'array',
|
|
398
385
|
items: {
|
|
399
|
-
type:
|
|
386
|
+
type: 'object',
|
|
400
387
|
properties: {
|
|
401
|
-
field: { type:
|
|
388
|
+
field: { type: 'string', example: 'email' },
|
|
402
389
|
message: {
|
|
403
|
-
type:
|
|
404
|
-
example:
|
|
390
|
+
type: 'string',
|
|
391
|
+
example: 'Invalid email address',
|
|
405
392
|
},
|
|
406
|
-
code: { type:
|
|
393
|
+
code: { type: 'string', example: 'invalid_format' },
|
|
407
394
|
},
|
|
408
395
|
},
|
|
409
396
|
},
|
|
410
|
-
requestId: { type:
|
|
397
|
+
requestId: { type: 'string', example: 'req_123456' },
|
|
411
398
|
},
|
|
412
399
|
},
|
|
413
400
|
},
|
|
@@ -417,32 +404,32 @@ export class OpenAPIGenerator {
|
|
|
417
404
|
|
|
418
405
|
// Auth error response
|
|
419
406
|
if (route.auth) {
|
|
420
|
-
responses[
|
|
421
|
-
description:
|
|
407
|
+
responses['401'] = {
|
|
408
|
+
description: 'Authentication required',
|
|
422
409
|
content: {
|
|
423
|
-
|
|
410
|
+
'application/json': {
|
|
424
411
|
schema: {
|
|
425
|
-
type:
|
|
412
|
+
type: 'object',
|
|
426
413
|
properties: {
|
|
427
|
-
success: { type:
|
|
428
|
-
error: { type:
|
|
429
|
-
requestId: { type:
|
|
414
|
+
success: { type: 'boolean', example: false },
|
|
415
|
+
error: { type: 'string', example: 'Authentication required' },
|
|
416
|
+
requestId: { type: 'string', example: 'req_123456' },
|
|
430
417
|
},
|
|
431
418
|
},
|
|
432
419
|
},
|
|
433
420
|
},
|
|
434
421
|
};
|
|
435
422
|
|
|
436
|
-
responses[
|
|
437
|
-
description:
|
|
423
|
+
responses['403'] = {
|
|
424
|
+
description: 'Insufficient permissions',
|
|
438
425
|
content: {
|
|
439
|
-
|
|
426
|
+
'application/json': {
|
|
440
427
|
schema: {
|
|
441
|
-
type:
|
|
428
|
+
type: 'object',
|
|
442
429
|
properties: {
|
|
443
|
-
success: { type:
|
|
444
|
-
error: { type:
|
|
445
|
-
requestId: { type:
|
|
430
|
+
success: { type: 'boolean', example: false },
|
|
431
|
+
error: { type: 'string', example: 'Insufficient permissions' },
|
|
432
|
+
requestId: { type: 'string', example: 'req_123456' },
|
|
446
433
|
},
|
|
447
434
|
},
|
|
448
435
|
},
|
|
@@ -452,17 +439,17 @@ export class OpenAPIGenerator {
|
|
|
452
439
|
|
|
453
440
|
// Rate limit error response
|
|
454
441
|
if (route.rateLimit) {
|
|
455
|
-
responses[
|
|
456
|
-
description:
|
|
442
|
+
responses['429'] = {
|
|
443
|
+
description: 'Rate limit exceeded',
|
|
457
444
|
content: {
|
|
458
|
-
|
|
445
|
+
'application/json': {
|
|
459
446
|
schema: {
|
|
460
|
-
type:
|
|
447
|
+
type: 'object',
|
|
461
448
|
properties: {
|
|
462
|
-
success: { type:
|
|
463
|
-
error: { type:
|
|
464
|
-
retryAfter: { type:
|
|
465
|
-
requestId: { type:
|
|
449
|
+
success: { type: 'boolean', example: false },
|
|
450
|
+
error: { type: 'string', example: 'Rate limit exceeded' },
|
|
451
|
+
retryAfter: { type: 'number', example: 60 },
|
|
452
|
+
requestId: { type: 'string', example: 'req_123456' },
|
|
466
453
|
},
|
|
467
454
|
},
|
|
468
455
|
},
|
|
@@ -471,16 +458,16 @@ export class OpenAPIGenerator {
|
|
|
471
458
|
}
|
|
472
459
|
|
|
473
460
|
// Server error response
|
|
474
|
-
responses[
|
|
475
|
-
description:
|
|
461
|
+
responses['500'] = {
|
|
462
|
+
description: 'Internal server error',
|
|
476
463
|
content: {
|
|
477
|
-
|
|
464
|
+
'application/json': {
|
|
478
465
|
schema: {
|
|
479
|
-
type:
|
|
466
|
+
type: 'object',
|
|
480
467
|
properties: {
|
|
481
|
-
success: { type:
|
|
482
|
-
error: { type:
|
|
483
|
-
requestId: { type:
|
|
468
|
+
success: { type: 'boolean', example: false },
|
|
469
|
+
error: { type: 'string', example: 'Internal server error' },
|
|
470
|
+
requestId: { type: 'string', example: 'req_123456' },
|
|
484
471
|
},
|
|
485
472
|
},
|
|
486
473
|
},
|
|
@@ -506,7 +493,7 @@ export class OpenAPIGenerator {
|
|
|
506
493
|
|
|
507
494
|
// Generate tags
|
|
508
495
|
private generateTags(): OpenAPITag[] {
|
|
509
|
-
return Array.from(this.tags).map(
|
|
496
|
+
return Array.from(this.tags).map(tag => ({
|
|
510
497
|
name: tag,
|
|
511
498
|
description: `Operations related to ${tag}`,
|
|
512
499
|
}));
|
|
@@ -515,7 +502,7 @@ export class OpenAPIGenerator {
|
|
|
515
502
|
// Convert Moro path format to OpenAPI path format
|
|
516
503
|
private convertPathToOpenAPI(path: string): string {
|
|
517
504
|
// Convert :param to {param} format
|
|
518
|
-
return path.replace(/:([^/]+)/g,
|
|
505
|
+
return path.replace(/:([^/]+)/g, '{$1}');
|
|
519
506
|
}
|
|
520
507
|
|
|
521
508
|
// Generate JSON representation
|
|
@@ -531,26 +518,26 @@ export class OpenAPIGenerator {
|
|
|
531
518
|
|
|
532
519
|
// Simple YAML converter (basic implementation)
|
|
533
520
|
private objectToYAML(obj: any, indent: number = 0): string {
|
|
534
|
-
const spaces =
|
|
535
|
-
let yaml =
|
|
521
|
+
const spaces = ' '.repeat(indent);
|
|
522
|
+
let yaml = '';
|
|
536
523
|
|
|
537
524
|
for (const [key, value] of Object.entries(obj)) {
|
|
538
525
|
if (value === null || value === undefined) continue;
|
|
539
526
|
|
|
540
527
|
yaml += `${spaces}${key}:`;
|
|
541
528
|
|
|
542
|
-
if (typeof value ===
|
|
543
|
-
yaml +=
|
|
529
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
530
|
+
yaml += '\n' + this.objectToYAML(value, indent + 1);
|
|
544
531
|
} else if (Array.isArray(value)) {
|
|
545
|
-
yaml +=
|
|
532
|
+
yaml += '\n';
|
|
546
533
|
for (const item of value) {
|
|
547
|
-
if (typeof item ===
|
|
534
|
+
if (typeof item === 'object') {
|
|
548
535
|
yaml += `${spaces} -\n` + this.objectToYAML(item, indent + 2);
|
|
549
536
|
} else {
|
|
550
537
|
yaml += `${spaces} - ${item}\n`;
|
|
551
538
|
}
|
|
552
539
|
}
|
|
553
|
-
} else if (typeof value ===
|
|
540
|
+
} else if (typeof value === 'string') {
|
|
554
541
|
yaml += ` "${value}"\n`;
|
|
555
542
|
} else {
|
|
556
543
|
yaml += ` ${value}\n`;
|
|
@@ -564,7 +551,7 @@ export class OpenAPIGenerator {
|
|
|
564
551
|
// Convenience function to generate OpenAPI from routes
|
|
565
552
|
export function generateOpenAPIFromRoutes(
|
|
566
553
|
routes: CompiledRoute[],
|
|
567
|
-
options: GenerationOptions
|
|
554
|
+
options: GenerationOptions
|
|
568
555
|
): OpenAPISpec {
|
|
569
556
|
const generator = new OpenAPIGenerator(options);
|
|
570
557
|
generator.addRoutes(routes);
|
|
@@ -574,15 +561,15 @@ export function generateOpenAPIFromRoutes(
|
|
|
574
561
|
// Default security schemes
|
|
575
562
|
export const defaultSecuritySchemes: Record<string, OpenAPISecurityScheme> = {
|
|
576
563
|
bearerAuth: {
|
|
577
|
-
type:
|
|
578
|
-
scheme:
|
|
579
|
-
bearerFormat:
|
|
580
|
-
description:
|
|
564
|
+
type: 'http',
|
|
565
|
+
scheme: 'bearer',
|
|
566
|
+
bearerFormat: 'JWT',
|
|
567
|
+
description: 'Bearer token authentication',
|
|
581
568
|
},
|
|
582
569
|
apiKey: {
|
|
583
|
-
type:
|
|
584
|
-
in:
|
|
585
|
-
name:
|
|
586
|
-
description:
|
|
570
|
+
type: 'apiKey',
|
|
571
|
+
in: 'header',
|
|
572
|
+
name: 'X-API-Key',
|
|
573
|
+
description: 'API key authentication',
|
|
587
574
|
},
|
|
588
575
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Simple Documentation Generator - Fallback for when Swagger UI has issues
|
|
2
2
|
// Generates clean, readable API documentation from routes
|
|
3
3
|
|
|
4
|
-
import { CompiledRoute, RouteSchema } from
|
|
5
|
-
import { createFrameworkLogger } from
|
|
4
|
+
import { CompiledRoute, RouteSchema } from '../routing';
|
|
5
|
+
import { createFrameworkLogger } from '../logger';
|
|
6
6
|
|
|
7
|
-
const logger = createFrameworkLogger(
|
|
7
|
+
const logger = createFrameworkLogger('SimpleDocs');
|
|
8
8
|
|
|
9
9
|
export interface SimpleDocsOptions {
|
|
10
10
|
title?: string;
|
|
@@ -17,19 +17,16 @@ export class SimpleDocsGenerator {
|
|
|
17
17
|
|
|
18
18
|
constructor(private options: SimpleDocsOptions = {}) {
|
|
19
19
|
this.options = {
|
|
20
|
-
title:
|
|
21
|
-
description:
|
|
22
|
-
basePath:
|
|
20
|
+
title: 'API Documentation',
|
|
21
|
+
description: 'API documentation generated from intelligent routes',
|
|
22
|
+
basePath: '/docs',
|
|
23
23
|
...options,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
addRoutes(routes: CompiledRoute[]): void {
|
|
28
28
|
this.routes = routes;
|
|
29
|
-
logger.debug(
|
|
30
|
-
`Added ${routes.length} routes to simple docs`,
|
|
31
|
-
"RouteAddition",
|
|
32
|
-
);
|
|
29
|
+
logger.debug(`Added ${routes.length} routes to simple docs`, 'RouteAddition');
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
generateHTML(): string {
|
|
@@ -156,7 +153,7 @@ export class SimpleDocsGenerator {
|
|
|
156
153
|
const grouped = new Map<string, CompiledRoute[]>();
|
|
157
154
|
|
|
158
155
|
for (const route of this.routes) {
|
|
159
|
-
const tags = route.schema.tags || [
|
|
156
|
+
const tags = route.schema.tags || ['default'];
|
|
160
157
|
|
|
161
158
|
for (const tag of tags) {
|
|
162
159
|
if (!grouped.has(tag)) {
|
|
@@ -169,10 +166,8 @@ export class SimpleDocsGenerator {
|
|
|
169
166
|
return grouped;
|
|
170
167
|
}
|
|
171
168
|
|
|
172
|
-
private generateRouteDocumentation(
|
|
173
|
-
|
|
174
|
-
): string {
|
|
175
|
-
let html = "";
|
|
169
|
+
private generateRouteDocumentation(routesByTag: Map<string, CompiledRoute[]>): string {
|
|
170
|
+
let html = '';
|
|
176
171
|
|
|
177
172
|
for (const [tag, routes] of routesByTag) {
|
|
178
173
|
html += `<h2>${tag.charAt(0).toUpperCase() + tag.slice(1)}</h2>`;
|
|
@@ -195,9 +190,9 @@ export class SimpleDocsGenerator {
|
|
|
195
190
|
<span class="path">${route.path}</span>
|
|
196
191
|
</div>
|
|
197
192
|
|
|
198
|
-
${route.description ? `<div class="description">${route.description}</div>` :
|
|
193
|
+
${route.description ? `<div class="description">${route.description}</div>` : ''}
|
|
199
194
|
|
|
200
|
-
${route.tags ? `<div class="tags">${route.tags.map(
|
|
195
|
+
${route.tags ? `<div class="tags">${route.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}</div>` : ''}
|
|
201
196
|
|
|
202
197
|
${this.generateValidationInfo(route)}
|
|
203
198
|
${this.generateAuthInfo(route)}
|
|
@@ -209,27 +204,25 @@ export class SimpleDocsGenerator {
|
|
|
209
204
|
}
|
|
210
205
|
|
|
211
206
|
private generateValidationInfo(route: RouteSchema): string {
|
|
212
|
-
if (!route.validation) return
|
|
207
|
+
if (!route.validation) return '';
|
|
213
208
|
|
|
214
209
|
const validationTypes = [];
|
|
215
|
-
if (route.validation.body) validationTypes.push(
|
|
216
|
-
if (route.validation.query) validationTypes.push(
|
|
217
|
-
if (route.validation.params) validationTypes.push(
|
|
218
|
-
if (route.validation.headers) validationTypes.push(
|
|
210
|
+
if (route.validation.body) validationTypes.push('Body');
|
|
211
|
+
if (route.validation.query) validationTypes.push('Query Parameters');
|
|
212
|
+
if (route.validation.params) validationTypes.push('Path Parameters');
|
|
213
|
+
if (route.validation.headers) validationTypes.push('Headers');
|
|
219
214
|
|
|
220
215
|
return `
|
|
221
216
|
<div class="validation">
|
|
222
|
-
<strong>Validation:</strong> ${validationTypes.join(
|
|
217
|
+
<strong>Validation:</strong> ${validationTypes.join(', ')}
|
|
223
218
|
<br><small>Request will be validated with Zod schemas for type safety</small>
|
|
224
219
|
</div>`;
|
|
225
220
|
}
|
|
226
221
|
|
|
227
222
|
private generateAuthInfo(route: RouteSchema): string {
|
|
228
|
-
if (!route.auth) return
|
|
223
|
+
if (!route.auth) return '';
|
|
229
224
|
|
|
230
|
-
const roles = route.auth.roles
|
|
231
|
-
? route.auth.roles.join(", ")
|
|
232
|
-
: "authenticated";
|
|
225
|
+
const roles = route.auth.roles ? route.auth.roles.join(', ') : 'authenticated';
|
|
233
226
|
|
|
234
227
|
return `
|
|
235
228
|
<div class="auth">
|
|
@@ -239,7 +232,7 @@ export class SimpleDocsGenerator {
|
|
|
239
232
|
}
|
|
240
233
|
|
|
241
234
|
private generateRateLimitInfo(route: RouteSchema): string {
|
|
242
|
-
if (!route.rateLimit) return
|
|
235
|
+
if (!route.rateLimit) return '';
|
|
243
236
|
|
|
244
237
|
const { requests, window } = route.rateLimit;
|
|
245
238
|
const windowSeconds = Math.round(window / 1000);
|
|
@@ -252,19 +245,19 @@ export class SimpleDocsGenerator {
|
|
|
252
245
|
}
|
|
253
246
|
|
|
254
247
|
private generateExamples(route: RouteSchema): string {
|
|
255
|
-
const baseUrl =
|
|
248
|
+
const baseUrl = 'http://localhost:3001';
|
|
256
249
|
const fullPath = `${baseUrl}${route.path}`;
|
|
257
250
|
|
|
258
|
-
let example =
|
|
251
|
+
let example = '';
|
|
259
252
|
|
|
260
|
-
if (route.method ===
|
|
253
|
+
if (route.method === 'GET') {
|
|
261
254
|
example = `curl "${fullPath}"`;
|
|
262
255
|
|
|
263
256
|
// Add query parameter example if validation exists
|
|
264
257
|
if (route.validation?.query) {
|
|
265
258
|
example = `curl "${fullPath}?limit=10&search=example"`;
|
|
266
259
|
}
|
|
267
|
-
} else if ([
|
|
260
|
+
} else if (['POST', 'PUT', 'PATCH'].includes(route.method)) {
|
|
268
261
|
example = `curl -X ${route.method} ${fullPath} \\
|
|
269
262
|
-H "Content-Type: application/json" \\
|
|
270
263
|
-d '{"example": "data"}'`;
|
|
@@ -283,19 +276,16 @@ export class SimpleDocsGenerator {
|
|
|
283
276
|
// Create middleware for simple docs
|
|
284
277
|
export function createSimpleDocsMiddleware(
|
|
285
278
|
routes: CompiledRoute[],
|
|
286
|
-
options: SimpleDocsOptions = {}
|
|
279
|
+
options: SimpleDocsOptions = {}
|
|
287
280
|
) {
|
|
288
281
|
const generator = new SimpleDocsGenerator(options);
|
|
289
282
|
generator.addRoutes(routes);
|
|
290
283
|
|
|
291
|
-
const basePath = options.basePath ||
|
|
284
|
+
const basePath = options.basePath || '/docs';
|
|
292
285
|
|
|
293
286
|
return (req: any, res: any, next: () => void) => {
|
|
294
|
-
if (
|
|
295
|
-
|
|
296
|
-
req.path === `${basePath}/simple/`
|
|
297
|
-
) {
|
|
298
|
-
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
287
|
+
if (req.path === `${basePath}/simple` || req.path === `${basePath}/simple/`) {
|
|
288
|
+
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
299
289
|
res.send(generator.generateHTML());
|
|
300
290
|
return;
|
|
301
291
|
}
|