@moostjs/swagger 0.3.9 → 0.3.11

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.
Files changed (3) hide show
  1. package/dist/index.cjs +516 -525
  2. package/dist/index.mjs +516 -525
  3. package/package.json +6 -6
package/dist/index.cjs CHANGED
@@ -22,7 +22,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22
22
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
23
  PERFORMANCE OF THIS SOFTWARE.
24
24
  ***************************************************************************** */
25
- /* global Reflect, Promise */
25
+ /* global Reflect, Promise, SuppressedError, Symbol */
26
26
 
27
27
 
28
28
  function __decorate(decorators, target, key, desc) {
@@ -40,467 +40,460 @@ function __metadata(metadataKey, metadataValue) {
40
40
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
41
41
  }
42
42
 
43
- function __awaiter(thisArg, _arguments, P, generator) {
44
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
45
- return new (P || (P = Promise))(function (resolve, reject) {
46
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
47
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
48
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
49
- step((generator = generator.apply(thisArg, _arguments || [])).next());
50
- });
51
- }
43
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
44
+ var e = new Error(message);
45
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
46
+ };
52
47
 
53
- function getSwaggerMate() {
54
- return moost.getMoostMate();
48
+ function getSwaggerMate() {
49
+ return moost.getMoostMate();
55
50
  }
56
51
 
57
- const SwaggerTag = (tag) => getSwaggerMate().decorate('swaggerTags', tag, true);
58
- const SwaggerExclude = () => getSwaggerMate().decorate('swaggerExclude', true);
59
- const SwaggerDescription = (descr) => getSwaggerMate().decorate('swaggerDescription', descr);
60
- function SwaggerResponse(code, opts) {
61
- return getSwaggerMate().decorate((meta) => {
62
- meta.swaggerResponses = meta.swaggerResponses || {};
63
- const keyCode = typeof code === 'number' ? code : 0;
64
- const opt = typeof code === 'number' ? opts : code;
65
- const contentType = typeof opt.contentType === 'string' ? opt.contentType : '*/*';
66
- // const description = typeof (opt as { description: string }).description === 'string' ? (opt as { description: string }).description : undefined
67
- const response = (['object', 'function'].includes(typeof opt.response) ? opt.response : opt);
68
- meta.swaggerResponses[keyCode] = meta.swaggerResponses[keyCode] || {};
69
- meta.swaggerResponses[keyCode][contentType] = response;
70
- // meta.swaggerResponses[keyCode].description = description
71
- return meta;
72
- });
73
- }
74
- function SwaggerRequestBody(opt) {
75
- return getSwaggerMate().decorate((meta) => {
76
- meta.swaggerRequestBody = meta.swaggerRequestBody || {};
77
- const contentType = typeof opt.contentType === 'string' ? opt.contentType : 'application/json';
78
- const response = (typeof opt.contentType === 'string' ? opt.response : opt);
79
- meta.swaggerRequestBody[contentType] = response;
80
- return meta;
81
- });
52
+ const SwaggerTag = (tag) => getSwaggerMate().decorate('swaggerTags', tag, true);
53
+ const SwaggerExclude = () => getSwaggerMate().decorate('swaggerExclude', true);
54
+ const SwaggerDescription = (descr) => getSwaggerMate().decorate('swaggerDescription', descr);
55
+ function SwaggerResponse(code, opts) {
56
+ return getSwaggerMate().decorate((meta) => {
57
+ meta.swaggerResponses = meta.swaggerResponses || {};
58
+ const keyCode = typeof code === 'number' ? code : 0;
59
+ const opt = typeof code === 'number' ? opts : code;
60
+ const contentType = typeof opt.contentType === 'string' ? opt.contentType : '*/*';
61
+ // const description = typeof (opt as { description: string }).description === 'string' ? (opt as { description: string }).description : undefined
62
+ const response = (['object', 'function'].includes(typeof opt.response) ? opt.response : opt);
63
+ meta.swaggerResponses[keyCode] = meta.swaggerResponses[keyCode] || {};
64
+ meta.swaggerResponses[keyCode][contentType] = response;
65
+ // meta.swaggerResponses[keyCode].description = description
66
+ return meta;
67
+ });
68
+ }
69
+ function SwaggerRequestBody(opt) {
70
+ return getSwaggerMate().decorate((meta) => {
71
+ meta.swaggerRequestBody = meta.swaggerRequestBody || {};
72
+ const contentType = typeof opt.contentType === 'string' ? opt.contentType : 'application/json';
73
+ const response = (typeof opt.contentType === 'string' ? opt.response : opt);
74
+ meta.swaggerRequestBody[contentType] = response;
75
+ return meta;
76
+ });
82
77
  }
83
78
 
84
- function mapToSwaggerSpec(metadata, options, logger) {
85
- var _a;
86
- const swaggerSpec = {
87
- openapi: '3.0.0',
88
- info: {
89
- title: (options === null || options === void 0 ? void 0 : options.title) || 'API Documentation',
90
- version: (options === null || options === void 0 ? void 0 : options.version) || '1.0.0',
91
- },
92
- paths: {},
93
- tags: [],
94
- components: {
95
- schemas: globalSchemas,
96
- },
97
- };
98
- for (const controller of metadata) {
99
- const cmeta = controller.meta;
100
- if (cmeta === null || cmeta === void 0 ? void 0 : cmeta.swaggerExclude)
101
- continue;
102
- const controllerTags = (cmeta === null || cmeta === void 0 ? void 0 : cmeta.swaggerTags) || [];
103
- for (const handler of controller.handlers) {
104
- const hmeta = handler.meta;
105
- const hh = handler.handler;
106
- if (hh.type !== 'HTTP' || (hmeta === null || hmeta === void 0 ? void 0 : hmeta.swaggerExclude) || !handler.registeredAs.length)
107
- continue;
108
- const handlerPath = handler.registeredAs[0].path;
109
- const handlerMethod = ((_a = hh.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'get';
110
- const handlerDescription = hmeta === null || hmeta === void 0 ? void 0 : hmeta.description;
111
- const handlerTags = [...controllerTags, ...((hmeta === null || hmeta === void 0 ? void 0 : hmeta.swaggerTags) || [])];
112
- if (!swaggerSpec.paths[handlerPath]) {
113
- swaggerSpec.paths[handlerPath] = {};
114
- }
115
- let responses = undefined;
116
- if (hmeta === null || hmeta === void 0 ? void 0 : hmeta.swaggerResponses) {
117
- for (const [code, responseConfigs] of Object.entries(hmeta.swaggerResponses)) {
118
- const newCode = code === '0' ? getDefaultStatusCode(handlerMethod) : code;
119
- for (const [contentType, type] of Object.entries(responseConfigs)) {
120
- let schema = undefined;
121
- let zt = undefined;
122
- if (type instanceof zod.z.ZodType) {
123
- zt = type;
124
- }
125
- else if (typeof type === 'function') {
126
- zt = zod.getZodType({
127
- type,
128
- });
129
- }
130
- if (zt) {
131
- const parsed = myParseZod(zt);
132
- if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
133
- schema = getSwaggerSchema(parsed);
134
- }
135
- }
136
- if (schema) {
137
- responses = responses || {};
138
- responses[newCode] = { content: { [contentType]: { schema } } };
139
- }
140
- }
141
- }
142
- }
143
- else if (hmeta === null || hmeta === void 0 ? void 0 : hmeta.returnType) {
144
- const parsed = myParseZod(zod.getZodType({
145
- type: hmeta.returnType,
146
- }));
147
- if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
148
- const schema = getSwaggerSchema(parsed);
149
- if (schema) {
150
- responses = responses || {};
151
- responses[getDefaultStatusCode(handlerMethod)] = {
152
- content: {
153
- '*/*': {
154
- schema,
155
- },
156
- },
157
- };
158
- }
159
- }
160
- }
161
- let reqBodyRequired = true;
162
- const bodyConfig = {};
163
- if (hmeta === null || hmeta === void 0 ? void 0 : hmeta.swaggerRequestBody) {
164
- for (const [contentType, type] of Object.entries(hmeta === null || hmeta === void 0 ? void 0 : hmeta.swaggerRequestBody)) {
165
- let zt;
166
- let schema;
167
- if (type instanceof zod.z.ZodType) {
168
- zt = type;
169
- }
170
- else if (typeof type === 'function') {
171
- zt = zod.getZodType({
172
- type,
173
- });
174
- }
175
- if (zt) {
176
- const parsed = myParseZod(zt);
177
- if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
178
- schema = getSwaggerSchema(parsed);
179
- }
180
- }
181
- bodyConfig[contentType] = { schema };
182
- }
183
- }
184
- swaggerSpec.paths[handlerPath][handlerMethod] = {
185
- summary: handlerDescription,
186
- operationId: handlerMethod.toUpperCase() + '_' + handlerPath.replace(/\//g, '_').replace(/[\{\}]/g, '__').replace(/[^A-Za-z0-9]/g, '_'),
187
- tags: handlerTags,
188
- parameters: [],
189
- responses,
190
- };
191
- const endpointSpec = swaggerSpec.paths[handlerPath][handlerMethod];
192
- for (const paramName of handler.registeredAs[0].args) {
193
- const paramIndex = handler.meta.params.findIndex(param => param.paramSource === 'ROUTE' && param.paramName === paramName);
194
- const paramMeta = handler.meta.params[paramIndex];
195
- let schema;
196
- let parsed;
197
- if (paramMeta) {
198
- const zodType = zod.getZodTypeForProp({
199
- type: controller.type,
200
- key: handler.method,
201
- index: paramIndex,
202
- }, {
203
- type: paramMeta.type,
204
- additionalMeta: paramMeta,
205
- }, undefined, logger);
206
- parsed = myParseZod(zodType);
207
- schema = getSwaggerSchema(parsed, true);
208
- }
209
- endpointSpec.parameters.push({
210
- name: paramName,
211
- in: 'path',
212
- description: paramMeta ? paramMeta.description : undefined,
213
- required: !(paramMeta === null || paramMeta === void 0 ? void 0 : paramMeta.optional) && !(parsed === null || parsed === void 0 ? void 0 : parsed.$optional),
214
- schema: schema || { type: 'string' },
215
- });
216
- }
217
- for (let i = 0; i < handler.meta.params.length; i++) {
218
- const paramMeta = handler.meta.params[i];
219
- if (paramMeta.paramSource && ['QUERY_ITEM', 'QUERY'].includes(paramMeta.paramSource)) {
220
- const zodType = zod.getZodTypeForProp({
221
- type: controller.type,
222
- key: handler.method,
223
- index: i,
224
- }, {
225
- type: paramMeta.type,
226
- additionalMeta: paramMeta,
227
- }, undefined, logger);
228
- const parsed = myParseZod(zodType);
229
- const schema = getSwaggerSchema(parsed, true);
230
- if (paramMeta.paramSource == 'QUERY_ITEM') {
231
- endpointSpec.parameters.push({
232
- name: paramMeta.paramName || '',
233
- in: 'query',
234
- description: paramMeta.description,
235
- required: !(paramMeta === null || paramMeta === void 0 ? void 0 : paramMeta.optional) && !(parsed === null || parsed === void 0 ? void 0 : parsed.$optional),
236
- schema: schema || { type: 'string' },
237
- });
238
- }
239
- else if (paramMeta.paramSource == 'QUERY') {
240
- if (parsed.$type === 'ZodObject') {
241
- for (const [key, value] of Object.entries(parsed.$inner)) {
242
- const schema = getSwaggerSchema(value, true);
243
- if (schema) {
244
- const swaggerSchema = {
245
- name: key,
246
- in: 'query',
247
- description: value.description,
248
- required: !parsed.$optional && !value.$optional,
249
- schema,
250
- };
251
- endpointSpec.parameters.push(swaggerSchema);
252
- }
253
- }
254
- }
255
- }
256
- }
257
- if ((paramMeta === null || paramMeta === void 0 ? void 0 : paramMeta.paramSource) === 'BODY') {
258
- const zodType = zod.getZodTypeForProp({
259
- type: controller.type,
260
- key: handler.method,
261
- index: i,
262
- }, {
263
- type: paramMeta.type,
264
- additionalMeta: paramMeta,
265
- }, undefined, logger);
266
- const parsed = myParseZod(zodType);
267
- let contentType = '';
268
- switch (parsed.$type) {
269
- case 'ZodString':
270
- case 'ZodNumber':
271
- case 'ZodBigInt':
272
- case 'ZodBoolean':
273
- case 'ZodDate':
274
- case 'ZodEnum':
275
- case 'ZodNativeEnum':
276
- case 'ZodLiteral':
277
- contentType = 'text/plan';
278
- break;
279
- default: contentType = 'application/json';
280
- }
281
- if (!bodyConfig[contentType]) {
282
- bodyConfig[contentType] = { schema: getSwaggerSchema(parsed) };
283
- }
284
- reqBodyRequired = !zodType.isOptional() && !paramMeta.optional;
285
- }
286
- }
287
- if (bodyConfig && Object.entries(bodyConfig).filter(e => !!e[1]).length > 0) {
288
- swaggerSpec.paths[handlerPath][handlerMethod].requestBody = {
289
- content: bodyConfig,
290
- required: reqBodyRequired,
291
- };
292
- }
293
- }
294
- }
295
- return swaggerSpec;
296
- }
297
- const globalSchemas = {};
298
- function getSwaggerSchema(parsed, forParam) {
299
- var _a, _b;
300
- const zodType = parsed.$ref;
301
- if (!forParam && zodType.__type_ref && globalSchemas[zodType.__type_ref.name])
302
- return { $ref: `#/components/schemas/${zodType.__type_ref.name}` };
303
- if (forParam && zodType.__type_ref && globalSchemas[zodType.__type_ref.name])
304
- return globalSchemas[zodType.__type_ref.name];
305
- const schema = {};
306
- if (!forParam && zodType.__type_ref) {
307
- globalSchemas[zodType.__type_ref.name] = schema;
308
- }
309
- function asString() {
310
- schema.type = 'string';
311
- if (parsed.$checks) {
312
- const { regex } = parsed.$checks;
313
- if (regex) {
314
- schema.pattern = regex.source;
315
- }
316
- }
317
- }
318
- function asLiteral() {
319
- if (parsed.$type === 'ZodLiteral') {
320
- schema.type = 'string';
321
- schema.enum = [parsed.$value];
322
- }
323
- }
324
- function asEnum() {
325
- if (parsed.$type === 'ZodEnum') {
326
- schema.type = 'string';
327
- schema.enum = parsed.$value;
328
- }
329
- }
330
- function asNativeEnum() {
331
- if (parsed.$type === 'ZodNativeEnum') {
332
- schema.type = 'string';
333
- schema.enum = Object.keys(parsed.$value);
334
- }
335
- }
336
- if (forParam) {
337
- switch (parsed.$type) {
338
- case 'ZodAny':
339
- case 'ZodUnknown':
340
- case 'ZodString':
341
- asString();
342
- break;
343
- case 'ZodNumber':
344
- schema.type = 'number';
345
- break;
346
- case 'ZodBigInt':
347
- schema.type = 'integer';
348
- break;
349
- case 'ZodBoolean':
350
- schema.type = 'boolean';
351
- break;
352
- case 'ZodLiteral':
353
- asLiteral();
354
- break;
355
- case 'ZodEnum':
356
- asEnum();
357
- break;
358
- case 'ZodNativeEnum':
359
- asNativeEnum();
360
- break;
361
- case 'ZodDate':
362
- schema.type = 'string';
363
- break;
364
- case 'ZodNull':
365
- schema.type = 'null';
366
- break;
367
- default: return undefined;
368
- }
369
- }
370
- else {
371
- switch (parsed.$type) {
372
- case 'ZodString':
373
- asString();
374
- break;
375
- case 'ZodNumber':
376
- schema.type = 'number';
377
- break;
378
- case 'ZodBigInt':
379
- schema.type = 'integer';
380
- break;
381
- case 'ZodBoolean':
382
- schema.type = 'boolean';
383
- break;
384
- case 'ZodLiteral':
385
- asLiteral();
386
- break;
387
- case 'ZodEnum':
388
- asEnum();
389
- break;
390
- case 'ZodNativeEnum':
391
- asNativeEnum();
392
- break;
393
- case 'ZodDate':
394
- schema.type = 'string';
395
- break;
396
- case 'ZodNull':
397
- schema.type = 'null';
398
- break;
399
- case 'ZodFunction':
400
- case 'ZodSymbol':
401
- case 'ZodUndefined':
402
- case 'ZodUnknown':
403
- case 'ZodNever':
404
- case 'ZodVoid':
405
- case 'ZodNaN':
406
- return undefined;
407
- // case 'ZodAny':
408
- case 'ZodArray':
409
- schema.type = 'array';
410
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
411
- schema.minItems = ((_a = parsed.$checks) === null || _a === void 0 ? void 0 : _a.minLength) || undefined;
412
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
413
- schema.maxItems = ((_b = parsed.$checks) === null || _b === void 0 ? void 0 : _b.maxLength) || undefined;
414
- schema.items = getSwaggerSchema(parsed.$inner);
415
- break;
416
- case 'ZodTuple':
417
- schema.type = 'array';
418
- schema.items = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
419
- break;
420
- case 'ZodObject':
421
- schema.type = 'object';
422
- schema.properties = {};
423
- schema.required = [];
424
- if (zodType._def.unknownKeys === 'passthrough')
425
- schema.additionalProperties = {};
426
- for (const [key, val] of Object.entries(parsed.$inner)) {
427
- const prop = getSwaggerSchema(val);
428
- if (prop) {
429
- schema.properties[key] = prop;
430
- if (!val.$optional)
431
- schema.required.push(key);
432
- }
433
- }
434
- break;
435
- case 'ZodPromise':
436
- case 'ZodRecord':
437
- case 'ZodMap':
438
- case 'ZodSet':
439
- schema.type = 'object';
440
- schema.properties = {};
441
- schema.additionalProperties = parsed.$type === 'ZodRecord' ? {} : undefined;
442
- break;
443
- case 'ZodUnion':
444
- case 'ZodDiscriminatedUnion':
445
- schema.oneOf = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
446
- break;
447
- case 'ZodIntersection':
448
- schema.allOf = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
449
- break;
450
- case 'ZodLazy':
451
- return getSwaggerSchema(parsed.$get());
452
- }
453
- }
454
- if (parsed.$nullable) {
455
- schema.nullable = parsed.$nullable;
456
- }
457
- if (parsed.$ref._def.description) {
458
- schema.description = parsed.$ref._def.description;
459
- }
460
- if (parsed.$checks) {
461
- const checks = parsed.$checks;
462
- if (parsed.$type === 'ZodString') {
463
- if (typeof checks.min === 'number')
464
- schema.minLength = checks.min;
465
- if (typeof checks.max === 'number')
466
- schema.maxLength = checks.max;
467
- }
468
- else {
469
- if (typeof checks.min === 'number')
470
- schema.minimum = checks.min;
471
- if (typeof checks.max === 'number')
472
- schema.maximum = checks.max;
473
- }
474
- }
475
- if (!forParam && zodType.__type_ref) {
476
- return { $ref: `#/components/schemas/${zodType.__type_ref.name}` };
477
- }
478
- return schema;
479
- }
480
- function myParseZod(schema) {
481
- return zodParser.parseZodType(schema);
482
- }
483
- function getDefaultStatusCode(httpMethod) {
484
- const defaultStatusCodes = {
485
- GET: 200,
486
- PUT: 200,
487
- POST: 201,
488
- DELETE: 204,
489
- };
490
- return defaultStatusCodes[httpMethod.toUpperCase()] || 200;
79
+ function mapToSwaggerSpec(metadata, options, logger) {
80
+ const swaggerSpec = {
81
+ openapi: '3.0.0',
82
+ info: {
83
+ title: options?.title || 'API Documentation',
84
+ version: options?.version || '1.0.0',
85
+ },
86
+ paths: {},
87
+ tags: [],
88
+ components: {
89
+ schemas: globalSchemas,
90
+ },
91
+ };
92
+ for (const controller of metadata) {
93
+ const cmeta = controller.meta;
94
+ if (cmeta?.swaggerExclude)
95
+ continue;
96
+ const controllerTags = cmeta?.swaggerTags || [];
97
+ for (const handler of controller.handlers) {
98
+ const hmeta = handler.meta;
99
+ const hh = handler.handler;
100
+ if (hh.type !== 'HTTP' || hmeta?.swaggerExclude || !handler.registeredAs.length)
101
+ continue;
102
+ const handlerPath = handler.registeredAs[0].path;
103
+ const handlerMethod = hh.method?.toLowerCase() || 'get';
104
+ const handlerDescription = hmeta?.description;
105
+ const handlerTags = [...controllerTags, ...(hmeta?.swaggerTags || [])];
106
+ if (!swaggerSpec.paths[handlerPath]) {
107
+ swaggerSpec.paths[handlerPath] = {};
108
+ }
109
+ let responses = undefined;
110
+ if (hmeta?.swaggerResponses) {
111
+ for (const [code, responseConfigs] of Object.entries(hmeta.swaggerResponses)) {
112
+ const newCode = code === '0' ? getDefaultStatusCode(handlerMethod) : code;
113
+ for (const [contentType, type] of Object.entries(responseConfigs)) {
114
+ let schema = undefined;
115
+ let zt = undefined;
116
+ if (type instanceof zod.z.ZodType) {
117
+ zt = type;
118
+ }
119
+ else if (typeof type === 'function') {
120
+ zt = zod.getZodType({
121
+ type,
122
+ });
123
+ }
124
+ if (zt) {
125
+ const parsed = myParseZod(zt);
126
+ if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
127
+ schema = getSwaggerSchema(parsed);
128
+ }
129
+ }
130
+ if (schema) {
131
+ responses = responses || {};
132
+ responses[newCode] = { content: { [contentType]: { schema } } };
133
+ }
134
+ }
135
+ }
136
+ }
137
+ else if (hmeta?.returnType) {
138
+ const parsed = myParseZod(zod.getZodType({
139
+ type: hmeta.returnType,
140
+ }));
141
+ if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
142
+ const schema = getSwaggerSchema(parsed);
143
+ if (schema) {
144
+ responses = responses || {};
145
+ responses[getDefaultStatusCode(handlerMethod)] = {
146
+ content: {
147
+ '*/*': {
148
+ schema,
149
+ },
150
+ },
151
+ };
152
+ }
153
+ }
154
+ }
155
+ let reqBodyRequired = true;
156
+ const bodyConfig = {};
157
+ if (hmeta?.swaggerRequestBody) {
158
+ for (const [contentType, type] of Object.entries(hmeta?.swaggerRequestBody)) {
159
+ let zt;
160
+ let schema;
161
+ if (type instanceof zod.z.ZodType) {
162
+ zt = type;
163
+ }
164
+ else if (typeof type === 'function') {
165
+ zt = zod.getZodType({
166
+ type,
167
+ });
168
+ }
169
+ if (zt) {
170
+ const parsed = myParseZod(zt);
171
+ if (['ZodString', 'ZodNumber', 'ZodObject', 'ZodArray', 'ZodBoolean'].includes(parsed.$type)) {
172
+ schema = getSwaggerSchema(parsed);
173
+ }
174
+ }
175
+ bodyConfig[contentType] = { schema };
176
+ }
177
+ }
178
+ swaggerSpec.paths[handlerPath][handlerMethod] = {
179
+ summary: handlerDescription,
180
+ operationId: handlerMethod.toUpperCase() + '_' + handlerPath.replace(/\//g, '_').replace(/[\{\}]/g, '__').replace(/[^A-Za-z0-9]/g, '_'),
181
+ tags: handlerTags,
182
+ parameters: [],
183
+ responses,
184
+ };
185
+ const endpointSpec = swaggerSpec.paths[handlerPath][handlerMethod];
186
+ for (const paramName of handler.registeredAs[0].args) {
187
+ const paramIndex = handler.meta.params.findIndex(param => param.paramSource === 'ROUTE' && param.paramName === paramName);
188
+ const paramMeta = handler.meta.params[paramIndex];
189
+ let schema;
190
+ let parsed;
191
+ if (paramMeta) {
192
+ const zodType = zod.getZodTypeForProp({
193
+ type: controller.type,
194
+ key: handler.method,
195
+ index: paramIndex,
196
+ }, {
197
+ type: paramMeta.type,
198
+ additionalMeta: paramMeta,
199
+ }, undefined, logger);
200
+ parsed = myParseZod(zodType);
201
+ schema = getSwaggerSchema(parsed, true);
202
+ }
203
+ endpointSpec.parameters.push({
204
+ name: paramName,
205
+ in: 'path',
206
+ description: paramMeta ? paramMeta.description : undefined,
207
+ required: !paramMeta?.optional && !parsed?.$optional,
208
+ schema: schema || { type: 'string' },
209
+ });
210
+ }
211
+ for (let i = 0; i < handler.meta.params.length; i++) {
212
+ const paramMeta = handler.meta.params[i];
213
+ if (paramMeta.paramSource && ['QUERY_ITEM', 'QUERY'].includes(paramMeta.paramSource)) {
214
+ const zodType = zod.getZodTypeForProp({
215
+ type: controller.type,
216
+ key: handler.method,
217
+ index: i,
218
+ }, {
219
+ type: paramMeta.type,
220
+ additionalMeta: paramMeta,
221
+ }, undefined, logger);
222
+ const parsed = myParseZod(zodType);
223
+ const schema = getSwaggerSchema(parsed, true);
224
+ if (paramMeta.paramSource == 'QUERY_ITEM') {
225
+ endpointSpec.parameters.push({
226
+ name: paramMeta.paramName || '',
227
+ in: 'query',
228
+ description: paramMeta.description,
229
+ required: !paramMeta?.optional && !parsed?.$optional,
230
+ schema: schema || { type: 'string' },
231
+ });
232
+ }
233
+ else if (paramMeta.paramSource == 'QUERY') {
234
+ if (parsed.$type === 'ZodObject') {
235
+ for (const [key, value] of Object.entries(parsed.$inner)) {
236
+ const schema = getSwaggerSchema(value, true);
237
+ if (schema) {
238
+ const swaggerSchema = {
239
+ name: key,
240
+ in: 'query',
241
+ description: value.description,
242
+ required: !parsed.$optional && !value.$optional,
243
+ schema,
244
+ };
245
+ endpointSpec.parameters.push(swaggerSchema);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ }
251
+ if (paramMeta?.paramSource === 'BODY') {
252
+ const zodType = zod.getZodTypeForProp({
253
+ type: controller.type,
254
+ key: handler.method,
255
+ index: i,
256
+ }, {
257
+ type: paramMeta.type,
258
+ additionalMeta: paramMeta,
259
+ }, undefined, logger);
260
+ const parsed = myParseZod(zodType);
261
+ let contentType = '';
262
+ switch (parsed.$type) {
263
+ case 'ZodString':
264
+ case 'ZodNumber':
265
+ case 'ZodBigInt':
266
+ case 'ZodBoolean':
267
+ case 'ZodDate':
268
+ case 'ZodEnum':
269
+ case 'ZodNativeEnum':
270
+ case 'ZodLiteral':
271
+ contentType = 'text/plan';
272
+ break;
273
+ default: contentType = 'application/json';
274
+ }
275
+ if (!bodyConfig[contentType]) {
276
+ bodyConfig[contentType] = { schema: getSwaggerSchema(parsed) };
277
+ }
278
+ reqBodyRequired = !zodType.isOptional() && !paramMeta.optional;
279
+ }
280
+ }
281
+ if (bodyConfig && Object.entries(bodyConfig).filter(e => !!e[1]).length > 0) {
282
+ swaggerSpec.paths[handlerPath][handlerMethod].requestBody = {
283
+ content: bodyConfig,
284
+ required: reqBodyRequired,
285
+ };
286
+ }
287
+ }
288
+ }
289
+ return swaggerSpec;
290
+ }
291
+ const globalSchemas = {};
292
+ function getSwaggerSchema(parsed, forParam) {
293
+ const zodType = parsed.$ref;
294
+ if (!forParam && zodType.__type_ref && globalSchemas[zodType.__type_ref.name])
295
+ return { $ref: `#/components/schemas/${zodType.__type_ref.name}` };
296
+ if (forParam && zodType.__type_ref && globalSchemas[zodType.__type_ref.name])
297
+ return globalSchemas[zodType.__type_ref.name];
298
+ const schema = {};
299
+ if (!forParam && zodType.__type_ref) {
300
+ globalSchemas[zodType.__type_ref.name] = schema;
301
+ }
302
+ function asString() {
303
+ schema.type = 'string';
304
+ if (parsed.$checks) {
305
+ const { regex } = parsed.$checks;
306
+ if (regex) {
307
+ schema.pattern = regex.source;
308
+ }
309
+ }
310
+ }
311
+ function asLiteral() {
312
+ if (parsed.$type === 'ZodLiteral') {
313
+ schema.type = 'string';
314
+ schema.enum = [parsed.$value];
315
+ }
316
+ }
317
+ function asEnum() {
318
+ if (parsed.$type === 'ZodEnum') {
319
+ schema.type = 'string';
320
+ schema.enum = parsed.$value;
321
+ }
322
+ }
323
+ function asNativeEnum() {
324
+ if (parsed.$type === 'ZodNativeEnum') {
325
+ schema.type = 'string';
326
+ schema.enum = Object.keys(parsed.$value);
327
+ }
328
+ }
329
+ if (forParam) {
330
+ switch (parsed.$type) {
331
+ case 'ZodAny':
332
+ case 'ZodUnknown':
333
+ case 'ZodString':
334
+ asString();
335
+ break;
336
+ case 'ZodNumber':
337
+ schema.type = 'number';
338
+ break;
339
+ case 'ZodBigInt':
340
+ schema.type = 'integer';
341
+ break;
342
+ case 'ZodBoolean':
343
+ schema.type = 'boolean';
344
+ break;
345
+ case 'ZodLiteral':
346
+ asLiteral();
347
+ break;
348
+ case 'ZodEnum':
349
+ asEnum();
350
+ break;
351
+ case 'ZodNativeEnum':
352
+ asNativeEnum();
353
+ break;
354
+ case 'ZodDate':
355
+ schema.type = 'string';
356
+ break;
357
+ case 'ZodNull':
358
+ schema.type = 'null';
359
+ break;
360
+ default: return undefined;
361
+ }
362
+ }
363
+ else {
364
+ switch (parsed.$type) {
365
+ case 'ZodString':
366
+ asString();
367
+ break;
368
+ case 'ZodNumber':
369
+ schema.type = 'number';
370
+ break;
371
+ case 'ZodBigInt':
372
+ schema.type = 'integer';
373
+ break;
374
+ case 'ZodBoolean':
375
+ schema.type = 'boolean';
376
+ break;
377
+ case 'ZodLiteral':
378
+ asLiteral();
379
+ break;
380
+ case 'ZodEnum':
381
+ asEnum();
382
+ break;
383
+ case 'ZodNativeEnum':
384
+ asNativeEnum();
385
+ break;
386
+ case 'ZodDate':
387
+ schema.type = 'string';
388
+ break;
389
+ case 'ZodNull':
390
+ schema.type = 'null';
391
+ break;
392
+ case 'ZodFunction':
393
+ case 'ZodSymbol':
394
+ case 'ZodUndefined':
395
+ case 'ZodUnknown':
396
+ case 'ZodNever':
397
+ case 'ZodVoid':
398
+ case 'ZodNaN':
399
+ return undefined;
400
+ // case 'ZodAny':
401
+ case 'ZodArray':
402
+ schema.type = 'array';
403
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
404
+ schema.minItems = parsed.$checks?.minLength || undefined;
405
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
406
+ schema.maxItems = parsed.$checks?.maxLength || undefined;
407
+ schema.items = getSwaggerSchema(parsed.$inner);
408
+ break;
409
+ case 'ZodTuple':
410
+ schema.type = 'array';
411
+ schema.items = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
412
+ break;
413
+ case 'ZodObject':
414
+ schema.type = 'object';
415
+ schema.properties = {};
416
+ schema.required = [];
417
+ if (zodType._def.unknownKeys === 'passthrough')
418
+ schema.additionalProperties = {};
419
+ for (const [key, val] of Object.entries(parsed.$inner)) {
420
+ const prop = getSwaggerSchema(val);
421
+ if (prop) {
422
+ schema.properties[key] = prop;
423
+ if (!val.$optional)
424
+ schema.required.push(key);
425
+ }
426
+ }
427
+ break;
428
+ case 'ZodPromise':
429
+ case 'ZodRecord':
430
+ case 'ZodMap':
431
+ case 'ZodSet':
432
+ schema.type = 'object';
433
+ schema.properties = {};
434
+ schema.additionalProperties = parsed.$type === 'ZodRecord' ? {} : undefined;
435
+ break;
436
+ case 'ZodUnion':
437
+ case 'ZodDiscriminatedUnion':
438
+ schema.oneOf = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
439
+ break;
440
+ case 'ZodIntersection':
441
+ schema.allOf = parsed.$inner.map(t => getSwaggerSchema(t)).filter(t => !!t);
442
+ break;
443
+ case 'ZodLazy':
444
+ return getSwaggerSchema(parsed.$get());
445
+ }
446
+ }
447
+ if (parsed.$nullable) {
448
+ schema.nullable = parsed.$nullable;
449
+ }
450
+ if (parsed.$ref._def.description) {
451
+ schema.description = parsed.$ref._def.description;
452
+ }
453
+ if (parsed.$checks) {
454
+ const checks = parsed.$checks;
455
+ if (parsed.$type === 'ZodString') {
456
+ if (typeof checks.min === 'number')
457
+ schema.minLength = checks.min;
458
+ if (typeof checks.max === 'number')
459
+ schema.maxLength = checks.max;
460
+ }
461
+ else {
462
+ if (typeof checks.min === 'number')
463
+ schema.minimum = checks.min;
464
+ if (typeof checks.max === 'number')
465
+ schema.maximum = checks.max;
466
+ }
467
+ }
468
+ if (!forParam && zodType.__type_ref) {
469
+ return { $ref: `#/components/schemas/${zodType.__type_ref.name}` };
470
+ }
471
+ return schema;
472
+ }
473
+ function myParseZod(schema) {
474
+ return zodParser.parseZodType(schema);
475
+ }
476
+ function getDefaultStatusCode(httpMethod) {
477
+ const defaultStatusCodes = {
478
+ GET: 200,
479
+ PUT: 200,
480
+ POST: 201,
481
+ DELETE: 204,
482
+ };
483
+ return defaultStatusCodes[httpMethod.toUpperCase()] || 200;
491
484
  }
492
485
 
493
- exports.SwaggerController = class SwaggerController {
494
- constructor(title = 'Moost API') {
495
- this.title = title;
496
- this.assetPath = swaggerUiDist.getAbsoluteFSPath();
497
- }
498
- serveIndex(url, location, status) {
499
- if (!url.endsWith('index.html') && !url.endsWith('/')) {
500
- status.value = 302;
501
- location.value = path.join(url, '/');
502
- return '';
503
- }
486
+ exports.SwaggerController = class SwaggerController {
487
+ constructor(title = 'Moost API') {
488
+ this.title = title;
489
+ this.assetPath = swaggerUiDist.getAbsoluteFSPath();
490
+ }
491
+ serveIndex(url, location, status) {
492
+ if (!url.endsWith('index.html') && !url.endsWith('/')) {
493
+ status.value = 302;
494
+ location.value = path.join(url, '/');
495
+ return '';
496
+ }
504
497
  return `<!DOCTYPE html>
505
498
  <html lang="en">
506
499
  <head>
@@ -518,9 +511,9 @@ exports.SwaggerController = class SwaggerController {
518
511
  <script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
519
512
  <script src="./swagger-initializer.js" charset="UTF-8"> </script>
520
513
  </body>
521
- </html>`;
522
- }
523
- 'swagger-initializer.js'() {
514
+ </html>`;
515
+ }
516
+ 'swagger-initializer.js'() {
524
517
  return `window.onload = function() {
525
518
  window.ui = SwaggerUIBundle({
526
519
  url: "./spec.json",
@@ -535,73 +528,71 @@ exports.SwaggerController = class SwaggerController {
535
528
  ],
536
529
  layout: "BaseLayout"
537
530
  });
538
- };`;
539
- }
540
- 'spec.json'() {
541
- return __awaiter(this, void 0, void 0, function* () {
542
- const logger = moost.useEventLogger('@moostjs/zod');
543
- if (!this.spec) {
544
- const { instantiate } = moost.useControllerContext();
545
- const moost$1 = yield instantiate(moost.Moost);
546
- this.spec = mapToSwaggerSpec(moost$1.getControllersOverview(), { title: this.title }, logger);
547
- }
548
- return this.spec;
549
- });
550
- }
551
- files(url) {
552
- return this.serve(url.split('/').pop());
553
- }
554
- serve(path) {
555
- return httpStatic.serveFile(path, {
556
- baseDir: this.assetPath,
557
- cacheControl: {
558
- public: true,
559
- maxAge: '1w',
560
- },
561
- });
562
- }
563
- };
564
- __decorate([
565
- eventHttp.Get(''),
566
- eventHttp.Get('//'),
567
- eventHttp.Get('index.html'),
568
- eventHttp.SetHeader('content-type', 'text/html'),
569
- __param(0, eventHttp.Url()),
570
- __param(1, eventHttp.HeaderHook('location')),
571
- __param(2, eventHttp.StatusHook()),
572
- __metadata("design:type", Function),
573
- __metadata("design:paramtypes", [String, Object, Object]),
574
- __metadata("design:returntype", void 0)
575
- ], exports.SwaggerController.prototype, "serveIndex", null);
576
- __decorate([
577
- eventHttp.Get(),
578
- eventHttp.SetHeader('content-type', 'application/javascript'),
579
- __metadata("design:type", Function),
580
- __metadata("design:paramtypes", []),
581
- __metadata("design:returntype", void 0)
582
- ], exports.SwaggerController.prototype, "swagger-initializer.js", null);
583
- __decorate([
584
- eventHttp.Get(),
585
- __metadata("design:type", Function),
586
- __metadata("design:paramtypes", []),
587
- __metadata("design:returntype", Promise)
588
- ], exports.SwaggerController.prototype, "spec.json", null);
589
- __decorate([
590
- eventHttp.Get('swagger-ui-bundle.*(js|js\\.map)'),
591
- eventHttp.Get('swagger-ui-standalone-preset.*(js|js\\.map)'),
592
- eventHttp.Get('swagger-ui.*(css|css\\.map)'),
593
- eventHttp.Get('index.*(css|css\\.map)'),
594
- __param(0, eventHttp.Url()),
595
- __metadata("design:type", Function),
596
- __metadata("design:paramtypes", [String]),
597
- __metadata("design:returntype", void 0)
598
- ], exports.SwaggerController.prototype, "files", null);
599
- exports.SwaggerController = __decorate([
600
- SwaggerExclude(),
601
- zod.ZodSkip(),
602
- moost.Controller('api-docs'),
603
- __param(0, moost.Const('Moost API')),
604
- __metadata("design:paramtypes", [Object])
531
+ };`;
532
+ }
533
+ async 'spec.json'() {
534
+ const logger = moost.useEventLogger('@moostjs/zod');
535
+ if (!this.spec) {
536
+ const { instantiate } = moost.useControllerContext();
537
+ const moost$1 = await instantiate(moost.Moost);
538
+ this.spec = mapToSwaggerSpec(moost$1.getControllersOverview(), { title: this.title }, logger);
539
+ }
540
+ return this.spec;
541
+ }
542
+ files(url) {
543
+ return this.serve(url.split('/').pop());
544
+ }
545
+ serve(path) {
546
+ return httpStatic.serveFile(path, {
547
+ baseDir: this.assetPath,
548
+ cacheControl: {
549
+ public: true,
550
+ maxAge: '1w',
551
+ },
552
+ });
553
+ }
554
+ };
555
+ __decorate([
556
+ eventHttp.Get(''),
557
+ eventHttp.Get('//'),
558
+ eventHttp.Get('index.html'),
559
+ eventHttp.SetHeader('content-type', 'text/html'),
560
+ __param(0, eventHttp.Url()),
561
+ __param(1, eventHttp.HeaderHook('location')),
562
+ __param(2, eventHttp.StatusHook()),
563
+ __metadata("design:type", Function),
564
+ __metadata("design:paramtypes", [String, Object, Object]),
565
+ __metadata("design:returntype", void 0)
566
+ ], exports.SwaggerController.prototype, "serveIndex", null);
567
+ __decorate([
568
+ eventHttp.Get(),
569
+ eventHttp.SetHeader('content-type', 'application/javascript'),
570
+ __metadata("design:type", Function),
571
+ __metadata("design:paramtypes", []),
572
+ __metadata("design:returntype", void 0)
573
+ ], exports.SwaggerController.prototype, "swagger-initializer.js", null);
574
+ __decorate([
575
+ eventHttp.Get(),
576
+ __metadata("design:type", Function),
577
+ __metadata("design:paramtypes", []),
578
+ __metadata("design:returntype", Promise)
579
+ ], exports.SwaggerController.prototype, "spec.json", null);
580
+ __decorate([
581
+ eventHttp.Get('swagger-ui-bundle.*(js|js\\.map)'),
582
+ eventHttp.Get('swagger-ui-standalone-preset.*(js|js\\.map)'),
583
+ eventHttp.Get('swagger-ui.*(css|css\\.map)'),
584
+ eventHttp.Get('index.*(css|css\\.map)'),
585
+ __param(0, eventHttp.Url()),
586
+ __metadata("design:type", Function),
587
+ __metadata("design:paramtypes", [String]),
588
+ __metadata("design:returntype", void 0)
589
+ ], exports.SwaggerController.prototype, "files", null);
590
+ exports.SwaggerController = __decorate([
591
+ SwaggerExclude(),
592
+ zod.ZodSkip(),
593
+ moost.Controller('api-docs'),
594
+ __param(0, moost.Const('Moost API')),
595
+ __metadata("design:paramtypes", [Object])
605
596
  ], exports.SwaggerController);
606
597
 
607
598
  exports.SwaggerDescription = SwaggerDescription;