@morojs/moro 1.4.0 → 1.5.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/core/config/index.d.ts +0 -1
- package/dist/core/config/index.js +0 -4
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.js +219 -226
- package/dist/core/config/loader.js.map +1 -1
- package/dist/core/config/schema.d.ts +30 -335
- package/dist/core/config/schema.js +133 -224
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +3 -2
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +0 -1
- package/dist/core/config/validation.js +5 -10
- package/dist/core/config/validation.js.map +1 -1
- package/dist/core/docs/index.js +1 -1
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/simple-docs.js +5 -5
- package/dist/core/docs/zod-to-openapi.d.ts +2 -3
- package/dist/core/docs/zod-to-openapi.js +28 -0
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/networking/websocket-manager.js +19 -19
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/validation/index.d.ts +0 -2
- package/dist/core/validation/index.js +3 -8
- package/dist/core/validation/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/moro.js +16 -15
- package/dist/moro.js.map +1 -1
- package/dist/{core/config/types.d.ts → types/config.d.ts} +0 -1
- package/dist/types/config.js +4 -0
- package/dist/types/config.js.map +1 -0
- package/package.json +6 -7
- package/src/core/config/index.ts +0 -3
- package/src/core/config/loader.ts +571 -247
- package/src/core/config/schema.ts +146 -279
- package/src/core/config/utils.ts +1 -2
- package/src/core/config/validation.ts +5 -10
- package/src/core/docs/index.ts +1 -1
- package/src/core/docs/simple-docs.ts +5 -5
- package/src/core/docs/zod-to-openapi.ts +50 -20
- package/src/core/networking/websocket-manager.ts +17 -17
- package/src/core/validation/index.ts +2 -8
- package/src/index.ts +11 -1
- package/src/moro.ts +16 -15
- package/src/{core/config/types.ts → types/config.ts} +0 -120
- package/dist/core/config/types.js +0 -124
- package/dist/core/config/types.js.map +0 -1
- package/dist/core/config/typescript-loader.d.ts +0 -6
- package/dist/core/config/typescript-loader.js +0 -268
- package/dist/core/config/typescript-loader.js.map +0 -1
- package/src/core/config/typescript-loader.ts +0 -571
|
@@ -1,283 +1,150 @@
|
|
|
1
1
|
// Core Configuration Schema for Moro Framework
|
|
2
|
-
import { z } from 'zod';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
.default(false)
|
|
125
|
-
.describe('Skip failed requests in rate limit counting'),
|
|
126
|
-
}),
|
|
127
|
-
|
|
128
|
-
validation: z.object({
|
|
129
|
-
enabled: z.coerce.boolean().default(true).describe('Enable validation by default'),
|
|
130
|
-
|
|
131
|
-
stripUnknown: z.coerce
|
|
132
|
-
.boolean()
|
|
133
|
-
.default(true)
|
|
134
|
-
.describe('Strip unknown properties from validated data'),
|
|
135
|
-
|
|
136
|
-
abortEarly: z.coerce.boolean().default(false).describe('Stop validation on first error'),
|
|
137
|
-
}),
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Logging Configuration Schema
|
|
141
|
-
const LoggingConfigSchema = z.object({
|
|
142
|
-
level: z
|
|
143
|
-
.enum(['debug', 'info', 'warn', 'error', 'fatal'])
|
|
144
|
-
.default('info')
|
|
145
|
-
.describe('Minimum log level'),
|
|
146
|
-
|
|
147
|
-
format: z.enum(['pretty', 'json', 'compact']).default('pretty').describe('Log output format'),
|
|
148
|
-
|
|
149
|
-
enableColors: z.coerce.boolean().default(true).describe('Enable colored log output'),
|
|
150
|
-
|
|
151
|
-
enableTimestamp: z.coerce.boolean().default(true).describe('Include timestamp in logs'),
|
|
152
|
-
|
|
153
|
-
enableContext: z.coerce.boolean().default(true).describe('Include context information in logs'),
|
|
154
|
-
|
|
155
|
-
outputs: z.object({
|
|
156
|
-
console: z.coerce.boolean().default(true),
|
|
157
|
-
file: z.object({
|
|
158
|
-
enabled: z.coerce.boolean().default(false),
|
|
159
|
-
path: z.string().default('./logs/moro.log'),
|
|
160
|
-
maxSize: z.string().default('10MB'),
|
|
161
|
-
maxFiles: z.coerce.number().default(5),
|
|
162
|
-
}),
|
|
163
|
-
webhook: z.object({
|
|
164
|
-
enabled: z.coerce.boolean().default(false),
|
|
165
|
-
url: z.string().url().optional(),
|
|
166
|
-
headers: z.record(z.string(), z.string()).default({}),
|
|
167
|
-
}),
|
|
168
|
-
}),
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Security Configuration Schema
|
|
172
|
-
const SecurityConfigSchema = z.object({
|
|
173
|
-
cors: z.object({
|
|
174
|
-
enabled: z.coerce.boolean().default(true),
|
|
175
|
-
origin: z.union([z.string(), z.array(z.string()), z.boolean()]).default('*'),
|
|
176
|
-
methods: z.array(z.string()).default(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']),
|
|
177
|
-
allowedHeaders: z.array(z.string()).default(['Content-Type', 'Authorization']),
|
|
178
|
-
credentials: z.coerce.boolean().default(false),
|
|
179
|
-
}),
|
|
180
|
-
|
|
181
|
-
helmet: z.object({
|
|
182
|
-
enabled: z.coerce.boolean().default(true),
|
|
183
|
-
contentSecurityPolicy: z.coerce.boolean().default(true),
|
|
184
|
-
hsts: z.coerce.boolean().default(true),
|
|
185
|
-
noSniff: z.coerce.boolean().default(true),
|
|
186
|
-
frameguard: z.coerce.boolean().default(true),
|
|
187
|
-
}),
|
|
188
|
-
|
|
189
|
-
rateLimit: z.object({
|
|
190
|
-
global: z.object({
|
|
191
|
-
enabled: z.coerce.boolean().default(false),
|
|
192
|
-
requests: z.coerce.number().min(1).default(1000),
|
|
193
|
-
window: z.coerce.number().min(1000).default(60000),
|
|
194
|
-
}),
|
|
195
|
-
}),
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
// External Services Configuration Schema
|
|
199
|
-
const ExternalServicesConfigSchema = z.object({
|
|
200
|
-
stripe: z
|
|
201
|
-
.object({
|
|
202
|
-
secretKey: z.string().optional(),
|
|
203
|
-
publishableKey: z.string().optional(),
|
|
204
|
-
webhookSecret: z.string().optional(),
|
|
205
|
-
apiVersion: z.string().default('2023-10-16'),
|
|
206
|
-
})
|
|
207
|
-
.optional(),
|
|
208
|
-
|
|
209
|
-
paypal: z
|
|
210
|
-
.object({
|
|
211
|
-
clientId: z.string().optional(),
|
|
212
|
-
clientSecret: z.string().optional(),
|
|
213
|
-
webhookId: z.string().optional(),
|
|
214
|
-
environment: z.enum(['sandbox', 'production']).default('sandbox'),
|
|
215
|
-
})
|
|
216
|
-
.optional(),
|
|
217
|
-
|
|
218
|
-
smtp: z
|
|
219
|
-
.object({
|
|
220
|
-
host: z.string().optional(),
|
|
221
|
-
port: z.coerce.number().min(1).max(65535).default(587),
|
|
222
|
-
secure: z.coerce.boolean().default(false),
|
|
223
|
-
username: z.string().optional(),
|
|
224
|
-
password: z.string().optional(),
|
|
225
|
-
})
|
|
226
|
-
.optional(),
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Performance Configuration Schema
|
|
230
|
-
const PerformanceConfigSchema = z.object({
|
|
231
|
-
compression: z.object({
|
|
232
|
-
enabled: z.coerce.boolean().default(true),
|
|
233
|
-
level: z.coerce.number().min(1).max(9).default(6),
|
|
234
|
-
threshold: z.coerce.number().min(0).default(1024),
|
|
235
|
-
}),
|
|
236
|
-
|
|
237
|
-
circuitBreaker: z.object({
|
|
238
|
-
enabled: z.coerce.boolean().default(true),
|
|
239
|
-
failureThreshold: z.coerce.number().min(1).default(5),
|
|
240
|
-
resetTimeout: z.coerce.number().min(1000).default(60000),
|
|
241
|
-
monitoringPeriod: z.coerce.number().min(1000).default(10000),
|
|
242
|
-
}),
|
|
243
|
-
|
|
244
|
-
clustering: z.object({
|
|
245
|
-
enabled: z.coerce.boolean().default(false),
|
|
246
|
-
workers: z.union([z.coerce.number().min(1), z.literal('auto')]).default(1),
|
|
247
|
-
}),
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Main Configuration Schema
|
|
251
|
-
export const ConfigSchema = z.object({
|
|
252
|
-
server: ServerConfigSchema,
|
|
253
|
-
serviceDiscovery: ServiceDiscoveryConfigSchema,
|
|
254
|
-
database: DatabaseConfigSchema,
|
|
255
|
-
modules: ModuleDefaultsConfigSchema,
|
|
256
|
-
logging: LoggingConfigSchema,
|
|
257
|
-
security: SecurityConfigSchema,
|
|
258
|
-
external: ExternalServicesConfigSchema,
|
|
259
|
-
performance: PerformanceConfigSchema,
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Inferred TypeScript types
|
|
263
|
-
export type AppConfig = z.infer<typeof ConfigSchema>;
|
|
264
|
-
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
265
|
-
export type ServiceDiscoveryConfig = z.infer<typeof ServiceDiscoveryConfigSchema>;
|
|
266
|
-
export type DatabaseConfig = z.infer<typeof DatabaseConfigSchema>;
|
|
267
|
-
export type ModuleDefaultsConfig = z.infer<typeof ModuleDefaultsConfigSchema>;
|
|
268
|
-
export type LoggingConfig = z.infer<typeof LoggingConfigSchema>;
|
|
269
|
-
export type SecurityConfig = z.infer<typeof SecurityConfigSchema>;
|
|
270
|
-
export type ExternalServicesConfig = z.infer<typeof ExternalServicesConfigSchema>;
|
|
271
|
-
export type PerformanceConfig = z.infer<typeof PerformanceConfigSchema>;
|
|
3
|
+
import { AppConfig } from '../../types/config';
|
|
4
|
+
|
|
5
|
+
// Default configuration values
|
|
6
|
+
export const DEFAULT_CONFIG: AppConfig = {
|
|
7
|
+
server: {
|
|
8
|
+
port: 3001,
|
|
9
|
+
host: 'localhost',
|
|
10
|
+
environment: 'development',
|
|
11
|
+
maxConnections: 1000,
|
|
12
|
+
timeout: 30000,
|
|
13
|
+
},
|
|
14
|
+
serviceDiscovery: {
|
|
15
|
+
enabled: false,
|
|
16
|
+
type: 'memory',
|
|
17
|
+
consulUrl: 'http://localhost:8500',
|
|
18
|
+
kubernetesNamespace: 'default',
|
|
19
|
+
healthCheckInterval: 30000,
|
|
20
|
+
retryAttempts: 3,
|
|
21
|
+
},
|
|
22
|
+
database: {
|
|
23
|
+
redis: {
|
|
24
|
+
url: 'redis://localhost:6379',
|
|
25
|
+
maxRetries: 3,
|
|
26
|
+
retryDelay: 1000,
|
|
27
|
+
keyPrefix: 'moro:',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
modules: {
|
|
31
|
+
cache: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
defaultTtl: 300,
|
|
34
|
+
maxSize: 1000,
|
|
35
|
+
strategy: 'lru',
|
|
36
|
+
},
|
|
37
|
+
rateLimit: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
defaultRequests: 100,
|
|
40
|
+
defaultWindow: 60000,
|
|
41
|
+
skipSuccessfulRequests: false,
|
|
42
|
+
skipFailedRequests: false,
|
|
43
|
+
},
|
|
44
|
+
validation: {
|
|
45
|
+
enabled: true,
|
|
46
|
+
stripUnknown: true,
|
|
47
|
+
abortEarly: false,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
logging: {
|
|
51
|
+
level: 'info',
|
|
52
|
+
format: 'pretty',
|
|
53
|
+
enableColors: true,
|
|
54
|
+
enableTimestamp: true,
|
|
55
|
+
enableContext: true,
|
|
56
|
+
outputs: {
|
|
57
|
+
console: true,
|
|
58
|
+
file: {
|
|
59
|
+
enabled: false,
|
|
60
|
+
path: './logs/moro.log',
|
|
61
|
+
maxSize: '10MB',
|
|
62
|
+
maxFiles: 5,
|
|
63
|
+
},
|
|
64
|
+
webhook: {
|
|
65
|
+
enabled: false,
|
|
66
|
+
headers: {},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
security: {
|
|
71
|
+
cors: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
origin: '*',
|
|
74
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
75
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
76
|
+
credentials: false,
|
|
77
|
+
},
|
|
78
|
+
helmet: {
|
|
79
|
+
enabled: true,
|
|
80
|
+
contentSecurityPolicy: true,
|
|
81
|
+
hsts: true,
|
|
82
|
+
noSniff: true,
|
|
83
|
+
frameguard: true,
|
|
84
|
+
},
|
|
85
|
+
rateLimit: {
|
|
86
|
+
global: {
|
|
87
|
+
enabled: false,
|
|
88
|
+
requests: 1000,
|
|
89
|
+
window: 60000,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
external: {
|
|
94
|
+
stripe: {
|
|
95
|
+
apiVersion: '2023-10-16',
|
|
96
|
+
},
|
|
97
|
+
paypal: {
|
|
98
|
+
environment: 'sandbox',
|
|
99
|
+
},
|
|
100
|
+
smtp: {
|
|
101
|
+
port: 587,
|
|
102
|
+
secure: false,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
performance: {
|
|
106
|
+
compression: {
|
|
107
|
+
enabled: true,
|
|
108
|
+
level: 6,
|
|
109
|
+
threshold: 1024,
|
|
110
|
+
},
|
|
111
|
+
circuitBreaker: {
|
|
112
|
+
enabled: true,
|
|
113
|
+
failureThreshold: 5,
|
|
114
|
+
resetTimeout: 60000,
|
|
115
|
+
monitoringPeriod: 10000,
|
|
116
|
+
},
|
|
117
|
+
clustering: {
|
|
118
|
+
enabled: false,
|
|
119
|
+
workers: 1,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
272
123
|
|
|
273
|
-
//
|
|
274
|
-
export {
|
|
275
|
-
|
|
276
|
-
ServiceDiscoveryConfigSchema,
|
|
277
|
-
DatabaseConfigSchema,
|
|
278
|
-
ModuleDefaultsConfigSchema,
|
|
279
|
-
LoggingConfigSchema,
|
|
280
|
-
SecurityConfigSchema,
|
|
281
|
-
ExternalServicesConfigSchema,
|
|
282
|
-
PerformanceConfigSchema,
|
|
124
|
+
// Simple compatibility export - just return the config as-is
|
|
125
|
+
export const ConfigSchema = {
|
|
126
|
+
parse: (data: any): AppConfig => data as AppConfig,
|
|
283
127
|
};
|
|
128
|
+
|
|
129
|
+
// Re-export types for backward compatibility
|
|
130
|
+
export type {
|
|
131
|
+
AppConfig,
|
|
132
|
+
ServerConfig,
|
|
133
|
+
ServiceDiscoveryConfig,
|
|
134
|
+
DatabaseConfig,
|
|
135
|
+
ModuleDefaultsConfig,
|
|
136
|
+
LoggingConfig,
|
|
137
|
+
SecurityConfig,
|
|
138
|
+
ExternalServicesConfig,
|
|
139
|
+
PerformanceConfig,
|
|
140
|
+
} from '../../types/config';
|
|
141
|
+
|
|
142
|
+
// For backward compatibility with modules that expect schema objects
|
|
143
|
+
export const ServerConfigSchema = { parse: (data: any) => data };
|
|
144
|
+
export const ServiceDiscoveryConfigSchema = { parse: (data: any) => data };
|
|
145
|
+
export const DatabaseConfigSchema = { parse: (data: any) => data };
|
|
146
|
+
export const ModuleDefaultsConfigSchema = { parse: (data: any) => data };
|
|
147
|
+
export const LoggingConfigSchema = { parse: (data: any) => data };
|
|
148
|
+
export const SecurityConfigSchema = { parse: (data: any) => data };
|
|
149
|
+
export const ExternalServicesConfigSchema = { parse: (data: any) => data };
|
|
150
|
+
export const PerformanceConfigSchema = { parse: (data: any) => data };
|
package/src/core/config/utils.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Configuration Utilities for Modules and Environment Handling
|
|
2
|
-
import { z } from 'zod';
|
|
3
2
|
import { AppConfig } from './schema';
|
|
4
3
|
import { createFrameworkLogger } from '../logger';
|
|
5
4
|
|
|
@@ -66,7 +65,7 @@ function coerceEnvironmentValue(value: string): any {
|
|
|
66
65
|
* Create module-specific configuration with environment override support
|
|
67
66
|
*/
|
|
68
67
|
export function createModuleConfig<T>(
|
|
69
|
-
schema:
|
|
68
|
+
schema: { parse: (data: any) => T },
|
|
70
69
|
defaultConfig: Partial<T>,
|
|
71
70
|
envPrefix?: string
|
|
72
71
|
): T {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Configuration Validation Functions
|
|
2
|
+
// Validation for config system with simple TypeScript functions
|
|
3
3
|
|
|
4
4
|
export class ConfigValidationError extends Error {
|
|
5
5
|
constructor(
|
|
@@ -12,7 +12,7 @@ export class ConfigValidationError extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
// Type-safe validation functions
|
|
15
|
+
// Type-safe validation functions for configuration
|
|
16
16
|
export function validatePort(value: unknown, field = 'port'): number {
|
|
17
17
|
const num = Number(value);
|
|
18
18
|
if (isNaN(num) || num < 1 || num > 65535) {
|
|
@@ -76,7 +76,7 @@ export function validateEnum<T extends string>(
|
|
|
76
76
|
return str as T;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
export function
|
|
79
|
+
export function validateStringArray(value: unknown, field = 'string array'): string[] {
|
|
80
80
|
if (!Array.isArray(value)) {
|
|
81
81
|
// Try to parse comma-separated string
|
|
82
82
|
if (typeof value === 'string') {
|
|
@@ -87,12 +87,7 @@ export function validateArray(value: unknown, field = 'array'): unknown[] {
|
|
|
87
87
|
}
|
|
88
88
|
throw new ConfigValidationError(field, value, 'Must be an array or comma-separated string');
|
|
89
89
|
}
|
|
90
|
-
return value;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function validateStringArray(value: unknown, field = 'string array'): string[] {
|
|
94
|
-
const arr = validateArray(value, field);
|
|
95
|
-
return arr.map((item, index) => validateString(item, `${field}[${index}]`));
|
|
90
|
+
return value.map((item, index) => validateString(item, `${field}[${index}]`));
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
export function validateOptional<T>(
|
package/src/core/docs/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Moro Framework Documentation System
|
|
2
|
-
// Automatic API documentation generation from intelligent routes and
|
|
2
|
+
// Automatic API documentation generation from intelligent routes and Validation schemas
|
|
3
3
|
|
|
4
4
|
import { CompiledRoute } from '../routing';
|
|
5
5
|
import { IntelligentRoutingManager } from '../routing/app-integration';
|
|
@@ -132,7 +132,7 @@ export class SimpleDocsGenerator {
|
|
|
132
132
|
<div class="container">
|
|
133
133
|
<h1>${this.options.title}</h1>
|
|
134
134
|
<p>${this.options.description}</p>
|
|
135
|
-
|
|
135
|
+
|
|
136
136
|
<div class="example">
|
|
137
137
|
<strong>Interactive Swagger UI:</strong> <a href="${this.options.basePath}" target="_blank">${this.options.basePath}</a><br>
|
|
138
138
|
<strong>OpenAPI JSON:</strong> <a href="${this.options.basePath}/openapi.json" target="_blank">${this.options.basePath}/openapi.json</a>
|
|
@@ -189,11 +189,11 @@ export class SimpleDocsGenerator {
|
|
|
189
189
|
<span class="method ${route.method}">${route.method}</span>
|
|
190
190
|
<span class="path">${route.path}</span>
|
|
191
191
|
</div>
|
|
192
|
-
|
|
192
|
+
|
|
193
193
|
${route.description ? `<div class="description">${route.description}</div>` : ''}
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
${route.tags ? `<div class="tags">${route.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}</div>` : ''}
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
${this.generateValidationInfo(route)}
|
|
198
198
|
${this.generateAuthInfo(route)}
|
|
199
199
|
${this.generateRateLimitInfo(route)}
|
|
@@ -215,7 +215,7 @@ export class SimpleDocsGenerator {
|
|
|
215
215
|
return `
|
|
216
216
|
<div class="validation">
|
|
217
217
|
<strong>Validation:</strong> ${validationTypes.join(', ')}
|
|
218
|
-
<br><small>Request will be validated with
|
|
218
|
+
<br><small>Request will be validated with Validation schemas for type safety</small>
|
|
219
219
|
</div>`;
|
|
220
220
|
}
|
|
221
221
|
|
|
@@ -1,22 +1,40 @@
|
|
|
1
1
|
// Zod to OpenAPI Schema Converter
|
|
2
2
|
// Transforms Zod schemas into OpenAPI 3.0 schema definitions
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
ZodSchema,
|
|
6
|
-
ZodType,
|
|
7
|
-
ZodObject,
|
|
8
|
-
ZodArray,
|
|
9
|
-
ZodString,
|
|
10
|
-
ZodNumber,
|
|
11
|
-
ZodBoolean,
|
|
12
|
-
ZodEnum,
|
|
13
|
-
ZodOptional,
|
|
14
|
-
ZodDefault,
|
|
15
|
-
ZodUnion,
|
|
16
|
-
ZodLiteral,
|
|
17
|
-
} from 'zod';
|
|
18
4
|
import { createFrameworkLogger } from '../logger';
|
|
19
5
|
|
|
6
|
+
// Dynamic Zod imports (optional dependency)
|
|
7
|
+
let ZodSchema: any,
|
|
8
|
+
ZodType: any,
|
|
9
|
+
ZodObject: any,
|
|
10
|
+
ZodArray: any,
|
|
11
|
+
ZodString: any,
|
|
12
|
+
ZodNumber: any,
|
|
13
|
+
ZodBoolean: any,
|
|
14
|
+
ZodEnum: any,
|
|
15
|
+
ZodOptional: any,
|
|
16
|
+
ZodDefault: any,
|
|
17
|
+
ZodUnion: any,
|
|
18
|
+
ZodLiteral: any;
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const zod = require('zod');
|
|
22
|
+
ZodSchema = zod.ZodSchema;
|
|
23
|
+
ZodType = zod.ZodType;
|
|
24
|
+
ZodObject = zod.ZodObject;
|
|
25
|
+
ZodArray = zod.ZodArray;
|
|
26
|
+
ZodString = zod.ZodString;
|
|
27
|
+
ZodNumber = zod.ZodNumber;
|
|
28
|
+
ZodBoolean = zod.ZodBoolean;
|
|
29
|
+
ZodEnum = zod.ZodEnum;
|
|
30
|
+
ZodOptional = zod.ZodOptional;
|
|
31
|
+
ZodDefault = zod.ZodDefault;
|
|
32
|
+
ZodUnion = zod.ZodUnion;
|
|
33
|
+
ZodLiteral = zod.ZodLiteral;
|
|
34
|
+
} catch {
|
|
35
|
+
// Zod not available - that's fine!
|
|
36
|
+
}
|
|
37
|
+
|
|
20
38
|
const logger = createFrameworkLogger('ZodToOpenAPI');
|
|
21
39
|
|
|
22
40
|
// OpenAPI schema types
|
|
@@ -52,7 +70,12 @@ export interface ConversionOptions {
|
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
// Main conversion function
|
|
55
|
-
export function zodToOpenAPI(schema:
|
|
73
|
+
export function zodToOpenAPI(schema: any, options: ConversionOptions = {}): OpenAPISchema {
|
|
74
|
+
// Check if Zod is available
|
|
75
|
+
if (!ZodSchema) {
|
|
76
|
+
throw new Error('Zod is not installed. Please install zod to use zodToOpenAPI function.');
|
|
77
|
+
}
|
|
78
|
+
|
|
56
79
|
const opts = {
|
|
57
80
|
includeExamples: true,
|
|
58
81
|
includeDescriptions: true,
|
|
@@ -367,7 +390,7 @@ function convertZodDefault(def: any, options: ConversionOptions): OpenAPISchema
|
|
|
367
390
|
|
|
368
391
|
// Convert ZodUnion
|
|
369
392
|
function convertZodUnion(def: any, options: ConversionOptions): OpenAPISchema {
|
|
370
|
-
const schemas = def.options.map((option:
|
|
393
|
+
const schemas = def.options.map((option: any) => convertZodType(option._def, options));
|
|
371
394
|
|
|
372
395
|
return {
|
|
373
396
|
oneOf: schemas,
|
|
@@ -386,16 +409,23 @@ function convertZodLiteral(def: any, options: ConversionOptions): OpenAPISchema
|
|
|
386
409
|
}
|
|
387
410
|
|
|
388
411
|
// Helper functions
|
|
389
|
-
function isOptionalType(type:
|
|
412
|
+
function isOptionalType(type: any): boolean {
|
|
390
413
|
return (type._def as any).typeName === 'ZodOptional';
|
|
391
414
|
}
|
|
392
415
|
|
|
393
|
-
function hasDefault(type:
|
|
416
|
+
function hasDefault(type: any): boolean {
|
|
394
417
|
return (type._def as any).typeName === 'ZodDefault';
|
|
395
418
|
}
|
|
396
419
|
|
|
397
420
|
// Generate example data from Zod schema
|
|
398
|
-
export function generateExampleFromSchema(schema:
|
|
421
|
+
export function generateExampleFromSchema(schema: any): any {
|
|
422
|
+
// Check if Zod is available
|
|
423
|
+
if (!ZodSchema) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
'Zod is not installed. Please install zod to use generateExampleFromSchema function.'
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
399
429
|
try {
|
|
400
430
|
return generateExample(schema._def);
|
|
401
431
|
} catch (error) {
|
|
@@ -441,7 +471,7 @@ function generateExample(def: any): any {
|
|
|
441
471
|
}
|
|
442
472
|
|
|
443
473
|
for (const [key, value] of Object.entries(shape)) {
|
|
444
|
-
const zodType = value as
|
|
474
|
+
const zodType = value as any;
|
|
445
475
|
if (!isOptionalType(zodType)) {
|
|
446
476
|
example[key] = generateExample(zodType._def);
|
|
447
477
|
}
|