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