vona-module-a-openapi 5.0.12 → 5.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,779 @@
1
- export * from "./.metadata/index.js";
2
- export * from "./lib/index.js";
3
- export * from "./types/index.js";
1
+ import { BeanSimple, appMetadata, appResource, cast, BeanInfo, BeanBase, LocaleModuleNameSeparator, HttpStatus, BeanScopeBase, isClassStrict, registerMappedClassMetadataKey, deepExtend } from 'vona';
2
+ import { Scope } from 'vona-module-a-bean';
3
+ import { locales as locales$1, setErrorMapDefault, setErrorMapSchema } from '@cabloy/zod-errors-custom';
4
+ import { OpenApiGeneratorV3, OpenApiGeneratorV31, OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
5
+ import * as ModuleInfo from '@cabloy/module-info';
6
+ import { isEmptyObject, isNil } from '@cabloy/utils';
7
+ import { toUpperCaseFirstChar } from '@cabloy/word-utils';
8
+ import { Service, SymbolRequestMappingHandler } from 'vona-module-a-web';
9
+ import { z } from 'zod';
10
+ import { coerceWithNil } from '@cabloy/zod-query';
11
+ import 'openapi3-ts/oas30';
12
+ import 'openapi3-ts/oas31';
13
+
14
+ var locale_en_us = locales$1['en-us'];
15
+
16
+ var locale_zh_cn = locales$1['zh-cn'];
17
+
18
+ function config(_app) {
19
+ return {
20
+ defaultVersion: 'V31',
21
+ generateDocument: {
22
+ V30: {
23
+ openapi: '3.0.0',
24
+ info: {
25
+ version: '5.0.0',
26
+ title: 'Vona',
27
+ description: 'Vona API'
28
+ }
29
+ },
30
+ V31: {
31
+ openapi: '3.1.0',
32
+ info: {
33
+ version: '5.0.0',
34
+ title: 'Vona',
35
+ description: 'Vona API'
36
+ }
37
+ }
38
+ },
39
+ securitySchemes: {
40
+ bearerAuth: {
41
+ type: 'http',
42
+ scheme: 'bearer',
43
+ bearerFormat: 'JWT'
44
+ }
45
+ }
46
+ };
47
+ }
48
+
49
+ function errorsAdapter(app) {
50
+ setErrorMapDefault((text, ...args) => {
51
+ return app.meta.text(text, ...args);
52
+ });
53
+ setErrorMapSchema((text, ...args) => {
54
+ return app.meta.text(text, ...args);
55
+ });
56
+ }
57
+
58
+ class Main extends BeanSimple {
59
+ async moduleLoading() {}
60
+ async moduleLoaded() {
61
+ errorsAdapter(this.app);
62
+ }
63
+ async configLoaded(_config) {}
64
+ }
65
+
66
+ function bodySchemaWrapperDefault(bodySchema) {
67
+ return z.object({
68
+ code: z.string(),
69
+ message: z.string(),
70
+ data: bodySchema
71
+ });
72
+ }
73
+
74
+ const SymbolDecoratorRule = Symbol('SymbolDecoratorRule');
75
+ const SymbolDecoratorRuleColumn = Symbol('SymbolDecoratorRuleColumn');
76
+
77
+ // not use z.ZodSchema
78
+
79
+ const SymbolRouteHandlersArgumentsMeta = Symbol('SymbolRouteHandlersArgumentsMeta');
80
+ const SymbolRouteHandlersArgumentsValue = Symbol('SymbolRouteHandlersArgumentsValue');
81
+
82
+ function $schema(classType, options) {
83
+ if (!classType) return z.any();
84
+ if (classType.parseAsync) return classType;
85
+ if (classType.name === 'String') return z.string();
86
+ if (classType.name === 'Number') return z.number();
87
+ if (classType.name === 'Boolean') return z.boolean();
88
+ if (classType.name === 'Date') return z.date();
89
+ if (classType.name === 'BigInt') return z.bigint();
90
+ if (classType.name === 'Array') return z.array(z.any());
91
+ // check if object
92
+ const rules = classType.prototype ? appMetadata.getMetadata(SymbolDecoratorRule, classType.prototype) : undefined;
93
+ if (!rules) {
94
+ // not object
95
+ return z.any();
96
+ }
97
+ // object
98
+ let schema = z.object(rules);
99
+ if (options?.passthrough) schema = schema.passthrough();
100
+ if (options?.strict) schema = schema.strict();
101
+ // refId
102
+ const beanOptions = appResource.getBean(classType);
103
+ if (beanOptions) {
104
+ const openapi = cast(beanOptions.options)?.openapi;
105
+ schema = schema.openapi(beanOptions.beanFullName, openapi);
106
+ }
107
+ return schema;
108
+ }
109
+
110
+ const SymbolOpenApiOptions = Symbol('SymbolOpenApiOptions');
111
+
112
+ var _dec$1, _dec2$1, _class$1;
113
+ const __ArgumentTypes = ['param', 'query', 'body', 'headers', 'fields', 'field', 'files', 'file'];
114
+ let ServiceOpenapi = (_dec$1 = Service(), _dec2$1 = BeanInfo({
115
+ module: "a-openapi"
116
+ }), _dec$1(_class$1 = _dec2$1(_class$1 = class ServiceOpenapi extends BeanBase {
117
+ generateJson(version = 'V31') {
118
+ const registry = this._collectRegistry();
119
+ const generator = version === 'V30' ? new OpenApiGeneratorV3(registry.definitions) : new OpenApiGeneratorV31(registry.definitions);
120
+ const apiObj = generator.generateDocument(this.scope.config.generateDocument[version]);
121
+ this._translate(apiObj);
122
+ return apiObj;
123
+ }
124
+ generateJsonOfControllerAction(controller, actionKey, version = 'V31') {
125
+ const registry = new OpenAPIRegistry();
126
+ const beanOptions = appResource.getBean(controller);
127
+ if (!beanOptions) throw new Error('invalid controller');
128
+ this._collectController(registry, beanOptions.module, controller, actionKey);
129
+ const generator = version === 'V30' ? new OpenApiGeneratorV3(registry.definitions) : new OpenApiGeneratorV31(registry.definitions);
130
+ const apiObj = generator.generateDocument(this.scope.config.generateDocument[version]);
131
+ this._translate(apiObj);
132
+ return apiObj;
133
+ }
134
+ _translate(apiObj) {
135
+ // paths
136
+ if (apiObj.paths) {
137
+ for (const key in apiObj.paths) {
138
+ const pathObj = apiObj.paths[key];
139
+ for (const method in pathObj) {
140
+ const methodObj = pathObj[method];
141
+ this._translateStrings(methodObj, ['description', 'summary']);
142
+ // parameters
143
+ for (const parameterObj of methodObj.parameters || []) {
144
+ this._translateSchema(parameterObj.schema);
145
+ }
146
+ // requestBody
147
+ this._translateSchema(methodObj.requestBody?.content?.['application/json']?.schema);
148
+ }
149
+ }
150
+ }
151
+ // components
152
+ if (apiObj.components?.schemas) {
153
+ for (const key in apiObj.components.schemas) {
154
+ const schema = apiObj.components.schemas[key];
155
+ this._translateSchema(schema);
156
+ }
157
+ }
158
+ }
159
+ _translateSchema(schema) {
160
+ if (!schema) return;
161
+ if (schema.type === 'object' && schema.required === undefined) schema.required = [];
162
+ this._translateStrings(schema, ['title', 'description']);
163
+ const properties = cast(schema).properties;
164
+ if (properties && typeof properties === 'object') {
165
+ for (const prop in properties) {
166
+ const propObj = properties[prop];
167
+ this._translateSchema(propObj);
168
+ }
169
+ }
170
+ }
171
+ _translateStrings(obj, keys) {
172
+ for (const key of keys) {
173
+ this._translateString(obj, key);
174
+ }
175
+ }
176
+ _translateString(obj, key) {
177
+ if (!obj) return;
178
+ if (obj[key] && obj[key].includes(LocaleModuleNameSeparator)) {
179
+ obj[key] = this.app.meta.text(obj[key]);
180
+ }
181
+ }
182
+ _collectRegistry() {
183
+ const registry = new OpenAPIRegistry();
184
+ // securitySchemes
185
+ const configSecuritySchemes = this.scope.config.securitySchemes;
186
+ for (const key in configSecuritySchemes) {
187
+ let securityScheme = configSecuritySchemes[key];
188
+ if (typeof securityScheme === 'function') {
189
+ securityScheme = securityScheme.call(this.app);
190
+ }
191
+ registry.registerComponent('securitySchemes', key, securityScheme);
192
+ }
193
+ // schema: independent
194
+ for (const sceneName of ['dto', 'entity']) {
195
+ const onionSlices = this.bean.onion[sceneName].getOnionsEnabled();
196
+ for (const onionSlice of onionSlices) {
197
+ if (onionSlice.beanOptions.options?.independent) {
198
+ const schema = $schema(onionSlice.beanOptions.beanClass);
199
+ registry.register(onionSlice.beanOptions.beanFullName, schema);
200
+ }
201
+ }
202
+ }
203
+ // controller
204
+ for (const controller of this.bean.onion.controller.getOnionsEnabled()) {
205
+ this._collectController(registry, controller.beanOptions.module, controller.beanOptions.beanClass);
206
+ }
207
+ return registry;
208
+ }
209
+ _collectController(registry, moduleName, controller, actionKey) {
210
+ // info
211
+ const info = ModuleInfo.parseInfo(moduleName);
212
+ // controller options
213
+ const beanOptions = appResource.getBean(controller);
214
+ if (!beanOptions) return;
215
+ const controllerBeanFullName = beanOptions.beanFullName;
216
+ const controllerOptions = beanOptions.options;
217
+ const controllerPath = controllerOptions.path;
218
+ const controllerOpenApiOptions = appMetadata.getMetadata(SymbolOpenApiOptions, controller);
219
+ if (controllerOpenApiOptions?.exclude) return;
220
+ // descs
221
+ const descs = Object.getOwnPropertyDescriptors(controller.prototype);
222
+ const actionKeys = actionKey ? [actionKey] : Object.keys(descs);
223
+ for (const actionKey of actionKeys) {
224
+ const desc = descs[actionKey];
225
+ if (['constructor'].includes(actionKey)) continue;
226
+ if (!desc.value || typeof desc.value !== 'function') continue;
227
+ this._registerControllerAction(registry, info, controller, beanOptions, controllerBeanFullName, controllerPath, controllerOpenApiOptions, actionKey, desc);
228
+ }
229
+ }
230
+ _registerControllerAction(registry, info, controller, beanOptions, _controllerBeanFullName, controllerPath, controllerOpenApiOptions, actionKey, _desc) {
231
+ // app
232
+ const app = this.app;
233
+
234
+ // action options: should not extend controllerOpenApiOptions
235
+ const actionOpenApiOptions = appMetadata.getMetadata(SymbolOpenApiOptions, controller.prototype, actionKey);
236
+ if (actionOpenApiOptions?.exclude) return;
237
+
238
+ // actionPath/actionMethod
239
+ if (!appMetadata.hasMetadata(SymbolRequestMappingHandler, controller.prototype, actionKey)) return;
240
+ const handlerMetadata = appMetadata.getMetadata(SymbolRequestMappingHandler, controller.prototype, actionKey);
241
+ const actionPath = handlerMetadata.path || '';
242
+ const actionMethod = handlerMetadata.method || 'get';
243
+
244
+ // routePath
245
+ const routePath = app.util.combineApiPathControllerAndAction(info.relativeName, controllerPath, actionPath, true, true);
246
+ // :id -> {id}
247
+ const routePath2 = routePath.replace(/:([^/]+)/g, '{$1}');
248
+
249
+ // tags
250
+ let tags = actionOpenApiOptions?.tags ?? controllerOpenApiOptions?.tags;
251
+ if (!tags || tags.length === 0) {
252
+ tags = [toUpperCaseFirstChar(this.app.util.combineResourceName(beanOptions.name, info.relativeName, true, true))];
253
+ }
254
+ // operationId
255
+ let operationId = actionOpenApiOptions?.operationId ?? actionKey;
256
+ operationId = `${tags[0]}_${operationId}`;
257
+ // security
258
+ const _public = actionOpenApiOptions?.public ?? controllerOpenApiOptions?.public;
259
+ let security;
260
+ if (!_public) {
261
+ security = [{
262
+ bearerAuth: []
263
+ }];
264
+ }
265
+ // registerPath
266
+ registry.registerPath({
267
+ tags,
268
+ method: actionMethod,
269
+ path: routePath2,
270
+ operationId,
271
+ security,
272
+ description: actionOpenApiOptions?.description,
273
+ summary: actionOpenApiOptions?.summary,
274
+ request: this._collectRequest(controller, actionKey, actionOpenApiOptions, controllerOpenApiOptions),
275
+ responses: this._collectResponses(controller, actionKey, actionOpenApiOptions)
276
+ });
277
+ }
278
+ _collectRequest(controller, actionKey, actionOpenApiOptions, controllerOpenApiOptions) {
279
+ // meta
280
+ const argsMeta = this._prepareArgsMeta(controller, actionKey, actionOpenApiOptions, controllerOpenApiOptions);
281
+ if (!argsMeta) return;
282
+ // args
283
+ const argsMapWithField = {};
284
+ const argsMapIsolate = {};
285
+ let isUpload;
286
+ for (const argMeta of argsMeta) {
287
+ if (!__ArgumentTypes.includes(argMeta.type)) continue;
288
+ if (['fields', 'field', 'files', 'file'].includes(argMeta.type)) {
289
+ isUpload = true;
290
+ }
291
+ if (argMeta.field) {
292
+ if (!argsMapWithField[argMeta.type]) {
293
+ argsMapWithField[argMeta.type] = {};
294
+ }
295
+ argsMapWithField[argMeta.type][argMeta.field] = argMeta.schema;
296
+ } else {
297
+ if (!argsMapIsolate[argMeta.type]) {
298
+ argsMapIsolate[argMeta.type] = argMeta.schema;
299
+ }
300
+ }
301
+ }
302
+ // request
303
+ const request = {};
304
+ if (isUpload) {
305
+ const schemaObj = {};
306
+ // not check argsMapIsolate.fields
307
+ if (argsMapWithField.fields) Object.assign(schemaObj, argsMapWithField.fields);
308
+ if (argsMapWithField.field) Object.assign(schemaObj, argsMapWithField.field);
309
+ if (argsMapWithField.files) Object.assign(schemaObj, argsMapWithField.files);
310
+ if (argsMapWithField.file) Object.assign(schemaObj, argsMapWithField.file);
311
+ if (argsMapIsolate.files) schemaObj.blobs = argsMapIsolate.files;
312
+ const schema = z.object(schemaObj);
313
+ // body
314
+ request.body = {
315
+ required: true,
316
+ content: {
317
+ 'multipart/form-data': {
318
+ schema
319
+ }
320
+ }
321
+ };
322
+ } else {
323
+ for (const argumentType of __ArgumentTypes) {
324
+ let schema = argsMapIsolate[argumentType];
325
+ if (argsMapWithField[argumentType]) {
326
+ if (!schema) {
327
+ schema = z.object(argsMapWithField[argumentType]);
328
+ } else {
329
+ schema = schema.extend(argsMapWithField[argumentType]);
330
+ }
331
+ }
332
+ if (!schema) continue;
333
+ // record
334
+ if (argumentType === 'body') {
335
+ // body
336
+ request.body = {
337
+ required: !schema.isOptional(),
338
+ content: {
339
+ 'application/json': {
340
+ schema
341
+ }
342
+ }
343
+ };
344
+ } else {
345
+ // others
346
+ const name = argumentType === 'param' ? 'params' : argumentType;
347
+ request[name] = schema;
348
+ }
349
+ }
350
+ }
351
+ return request;
352
+ }
353
+ _collectResponses(controller, actionKey, actionOpenApiOptions) {
354
+ // contentType
355
+ const contentType = actionOpenApiOptions?.contentType || 'application/json';
356
+ // body schema
357
+ const bodySchema = this._parseBodySchema(controller, actionKey, actionOpenApiOptions, contentType);
358
+ // response
359
+ const response = {
360
+ description: '',
361
+ content: {
362
+ [contentType]: {
363
+ schema: bodySchema
364
+ }
365
+ }
366
+ };
367
+ // responses
368
+ const responses = {
369
+ [HttpStatus.OK]: response
370
+ };
371
+ return responses;
372
+ }
373
+ _parseBodySchema(controller, actionKey, actionOpenApiOptions, contentType) {
374
+ // bodySchema
375
+ let bodySchema;
376
+ if (actionOpenApiOptions?.bodySchema) {
377
+ bodySchema = actionOpenApiOptions.bodySchema;
378
+ } else {
379
+ const metaType = appMetadata.getDesignReturntype(controller.prototype, actionKey);
380
+ bodySchema = $schema(metaType);
381
+ }
382
+ // wrapper
383
+ if (contentType !== 'application/json') return bodySchema;
384
+ if (actionOpenApiOptions?.bodySchemaWrapper === false) return bodySchema;
385
+ const wrapper = actionOpenApiOptions?.bodySchemaWrapper ?? bodySchemaWrapperDefault;
386
+ return wrapper(bodySchema);
387
+ }
388
+ _prepareArgsMeta(controller, actionKey, actionOpenApiOptions, controllerOpenApiOptions) {
389
+ // meta
390
+ let argsMeta = appMetadata.getMetadata(SymbolRouteHandlersArgumentsMeta, controller.prototype, actionKey);
391
+ // headers
392
+ const objHeaders = Object.assign({}, this._combineArgHeaders(controllerOpenApiOptions?.headers), this._combineArgHeaders(actionOpenApiOptions?.headers));
393
+ // public
394
+ const _public = actionOpenApiOptions?.public ?? controllerOpenApiOptions?.public;
395
+ if (!_public && !objHeaders.Authorization) {
396
+ objHeaders.Authorization = z.string().optional();
397
+ }
398
+ if (isEmptyObject(objHeaders)) return argsMeta;
399
+ // merge
400
+ if (!argsMeta) argsMeta = [];
401
+ let argHeaders = argsMeta.find(item => item.type === 'headers' && !item.field);
402
+ if (!argHeaders) {
403
+ argHeaders = {
404
+ type: 'headers',
405
+ field: undefined,
406
+ schema: z.object(objHeaders)
407
+ };
408
+ argsMeta.push(argHeaders);
409
+ } else {
410
+ if (!argHeaders.schema.extend) throw new Error(`headers schema is not valid: ${actionKey}`);
411
+ argHeaders.schema = argHeaders.schema.extend(objHeaders);
412
+ }
413
+ return argsMeta;
414
+ }
415
+ _combineArgHeaders(headers) {
416
+ if (!headers) return;
417
+ const objHeaders = {};
418
+ for (const header of headers) {
419
+ objHeaders[header.name] = z.string().openapi({
420
+ description: header.description
421
+ });
422
+ }
423
+ return objHeaders;
424
+ }
425
+ }) || _class$1) || _class$1);
426
+
427
+ var _dec, _dec2, _class;
428
+ const locales = {
429
+ 'en-us': locale_en_us,
430
+ 'zh-cn': locale_zh_cn
431
+ };
432
+ let ScopeModuleAOpenapi = (_dec = Scope(), _dec2 = BeanInfo({
433
+ module: "a-openapi"
434
+ }), _dec(_class = _dec2(_class = class ScopeModuleAOpenapi extends BeanScopeBase {}) || _class) || _class);
435
+ function $locale(key) {
436
+ return `a-openapi::${key}`;
437
+ }
438
+ /** scope: end */
439
+
440
+ function makeSchemaLikes(schemaLikes, typeInit) {
441
+ // default schema
442
+ let argSchema = $schema(typeInit);
443
+ // loop
444
+ for (let index = schemaLikes.length - 1; index >= 0; index--) {
445
+ const schemaLike = schemaLikes[index];
446
+ argSchema = makeSchemaLike(schemaLike, argSchema);
447
+ }
448
+ return argSchema;
449
+ }
450
+ function makeSchemaLike(schemaLike, schemaPrevious) {
451
+ if (!schemaLike) return schemaPrevious;
452
+ if (Object.prototype.hasOwnProperty.call(schemaLike, 'parseAsync')) {
453
+ // schema
454
+ return schemaLike;
455
+ } else if (isClassStrict(schemaLike) || ['String', 'Number', 'Boolean', 'Date', 'BigInt', 'Array'].includes(cast(schemaLike).name)) {
456
+ // class
457
+ return $schema(cast(schemaLike));
458
+ } else {
459
+ // function
460
+ return cast(schemaLike)(schemaPrevious);
461
+ }
462
+ }
463
+
464
+ function getTargetDecoratorRules(target) {
465
+ registerMappedClassMetadataKey(target, SymbolDecoratorRule, {
466
+ partialClass: meta => {
467
+ return meta.optional();
468
+ }
469
+ });
470
+ return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRule, target);
471
+ }
472
+ function getTargetDecoratorRuleColumns(target) {
473
+ registerMappedClassMetadataKey(target, SymbolDecoratorRuleColumn);
474
+ return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRuleColumn, target);
475
+ }
476
+ function mergeFieldsOpenAPIMetadata(target) {
477
+ // rules
478
+ const rules = getTargetDecoratorRules(target.prototype);
479
+ // beanOptions
480
+ const beanOptions = appResource.getBean(target);
481
+ const fields = cast(beanOptions?.options)?.fields;
482
+ if (!fields) return;
483
+ for (const key in fields) {
484
+ const field = fields[key];
485
+ if (!field) continue;
486
+ const schemaCurrent = rules[key];
487
+ if (Object.prototype.hasOwnProperty.call(field, 'parseAsync')) {
488
+ const schema = field;
489
+ rules[key] = schema.openapi(deepExtend({}, schemaCurrent?._def.openapi?.metadata, schema._def.openapi?.metadata));
490
+ } else {
491
+ // use deepExtend for sure strict
492
+ if (schemaCurrent) {
493
+ rules[key] = schemaCurrent.openapi(deepExtend({}, schemaCurrent._def.openapi?.metadata, field));
494
+ } else {
495
+ rules[key] = z.any().openapi(deepExtend({}, field));
496
+ }
497
+ }
498
+ }
499
+ }
500
+
501
+ function Field$1(...schemaLikes) {
502
+ return function (target, prop) {
503
+ // rules
504
+ const rules = getTargetDecoratorRules(target);
505
+ // rule
506
+ const metaType = appMetadata.getDesignType(target, prop);
507
+ rules[prop] = makeSchemaLikes(schemaLikes, metaType);
508
+ //
509
+ const columns = getTargetDecoratorRuleColumns(target);
510
+ columns[prop] = prop;
511
+ };
512
+ }
513
+
514
+ function setPublic(target, prop, _descriptor, value) {
515
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
516
+ options.public = value;
517
+ }
518
+ function contentType(contentType) {
519
+ return function (target, prop, descriptor) {
520
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
521
+ options.contentType = contentType;
522
+ return descriptor;
523
+ };
524
+ }
525
+ function body(...schemaLikes) {
526
+ return function (target, prop, descriptor) {
527
+ // schema
528
+ const metaType = appMetadata.getDesignReturntype(target, prop);
529
+ const schema = makeSchemaLikes(schemaLikes, metaType);
530
+ // options
531
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
532
+ options.bodySchema = schema;
533
+ return descriptor;
534
+ };
535
+ }
536
+ function bodyCustom(bodySchemaWrapper, ...schemaLikes) {
537
+ return function (target, prop, descriptor) {
538
+ // schema
539
+ const metaType = appMetadata.getDesignReturntype(target, prop);
540
+ const schema = makeSchemaLikes(schemaLikes, metaType);
541
+ // options
542
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
543
+ options.bodySchema = schema;
544
+ options.bodySchemaWrapper = bodySchemaWrapper;
545
+ return descriptor;
546
+ };
547
+ }
548
+ function exclude() {
549
+ return function (target, prop, descriptor) {
550
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
551
+ options.exclude = true;
552
+ return descriptor;
553
+ };
554
+ }
555
+ function tags(tags) {
556
+ return function (target, prop, descriptor) {
557
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
558
+ options.tags = tags;
559
+ return descriptor;
560
+ };
561
+ }
562
+ function header(header) {
563
+ return function (target, prop, descriptor) {
564
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
565
+ if (!options.headers) options.headers = [];
566
+ options.headers.push(header);
567
+ return descriptor;
568
+ };
569
+ }
570
+ function headers(headers) {
571
+ return function (target, prop, descriptor) {
572
+ const options = appMetadata.getOwnMetadataMap(false, SymbolOpenApiOptions, target, prop);
573
+ if (!options.headers) options.headers = [];
574
+ options.headers.push(...headers);
575
+ return descriptor;
576
+ };
577
+ }
578
+ const Api = {
579
+ field: Field$1,
580
+ contentType,
581
+ body,
582
+ bodyCustom,
583
+ exclude,
584
+ tags,
585
+ header,
586
+ headers
587
+ };
588
+
589
+ function createPipesArgumentDecorator(paramType, extractValue) {
590
+ return function (field, ...schemaLikes) {
591
+ return function (target, prop, index) {
592
+ // not inherit
593
+ const argsMeta = appMetadata.getOwnMetadataArray(false, SymbolRouteHandlersArgumentsMeta, target, prop);
594
+ const hasParamField = typeof field === 'string';
595
+ const paramField = hasParamField ? field : undefined;
596
+ const paramSchemaLikes = hasParamField ? schemaLikes : [field, ...schemaLikes].filter(item => !!item);
597
+ const paramtypes = appMetadata.getMetadata('design:paramtypes', target, prop);
598
+ let metaType;
599
+ if (paramType === 'file') {
600
+ metaType = z.string().openapi({
601
+ format: 'binary'
602
+ });
603
+ } else if (paramType === 'files') {
604
+ metaType = z.array(z.string().openapi({
605
+ format: 'binary'
606
+ }));
607
+ } else {
608
+ metaType = paramtypes[index];
609
+ }
610
+ const argSchema = makeSchemaLikes(paramSchemaLikes, metaType);
611
+ argsMeta.push({
612
+ index,
613
+ type: paramType,
614
+ field: paramField,
615
+ pipes: [argSchema],
616
+ schema: argSchema,
617
+ extractValue
618
+ });
619
+ };
620
+ };
621
+ }
622
+
623
+ function Param(property, ...schemaLikes) {
624
+ return createPipesArgumentDecorator('param')(property, ...schemaLikes);
625
+ }
626
+ function Query(property, ...schemaLikes) {
627
+ return createPipesArgumentDecorator('query')(property, ...schemaLikes);
628
+ }
629
+ function Body(property, ...schemaLikes) {
630
+ return createPipesArgumentDecorator('body')(property, ...schemaLikes);
631
+ }
632
+ function Headers(property, ...schemaLikes) {
633
+ return createPipesArgumentDecorator('headers')(property, ...schemaLikes);
634
+ }
635
+ function Fields(property, ...schemaLikes) {
636
+ return createPipesArgumentDecorator('fields')(property, ...schemaLikes);
637
+ }
638
+ function Field(property, ...schemaLikes) {
639
+ return createPipesArgumentDecorator('field')(property, ...schemaLikes);
640
+ }
641
+ function Files(property, ...schemaLikes) {
642
+ return createPipesArgumentDecorator('files')(property, ...schemaLikes);
643
+ }
644
+ function File(property, ...schemaLikes) {
645
+ return createPipesArgumentDecorator('file')(property, ...schemaLikes);
646
+ }
647
+ function User(...schemaLikes) {
648
+ return createPipesArgumentDecorator('user')(undefined, ...schemaLikes);
649
+ }
650
+ const Arg = {
651
+ param: Param,
652
+ query: Query,
653
+ body: Body,
654
+ headers: Headers,
655
+ fields: Fields,
656
+ field: Field,
657
+ files: Files,
658
+ file: File,
659
+ user: User
660
+ };
661
+
662
+ function schemaEmail(message) {
663
+ return function (schema) {
664
+ return schema.email(message);
665
+ };
666
+ }
667
+ function schemaUrl(message) {
668
+ return function (schema) {
669
+ return schema.url(message);
670
+ };
671
+ }
672
+ function schemaUuid(message) {
673
+ return function (schema) {
674
+ return schema.uuid(message);
675
+ };
676
+ }
677
+ function schemaIp(options) {
678
+ return function (schema) {
679
+ return schema.ip(options);
680
+ };
681
+ }
682
+ function schemaMin(min, message) {
683
+ return function (schema) {
684
+ return schema.min(min, message);
685
+ };
686
+ }
687
+ function schemaMax(max, message) {
688
+ return function (schema) {
689
+ return schema.max(max, message);
690
+ };
691
+ }
692
+ function schemaTableIdentity() {
693
+ return function (_schema) {
694
+ return z.union([z.string(), z.number()]);
695
+ };
696
+ }
697
+
698
+ function schemaOpenapi(refId, metadata) {
699
+ return function (schema) {
700
+ return schema.openapi(refId, metadata);
701
+ };
702
+ }
703
+ function schemaTitle(title) {
704
+ return function (schema) {
705
+ return schema.openapi({
706
+ title
707
+ });
708
+ };
709
+ }
710
+ function schemaDescription(description) {
711
+ return function (schema) {
712
+ return schema.openapi({
713
+ description
714
+ });
715
+ };
716
+ }
717
+ function schemaExample(example) {
718
+ return function (schema) {
719
+ return schema.openapi({
720
+ example
721
+ });
722
+ };
723
+ }
724
+
725
+ function schemaDefault(defaultValue) {
726
+ return function (schema) {
727
+ return schema.default(defaultValue);
728
+ };
729
+ }
730
+ function schemaOptional() {
731
+ return function (schema) {
732
+ return schema.optional();
733
+ };
734
+ }
735
+ function schemaObject(classType, options) {
736
+ return function (_schema) {
737
+ return $schema(classType, options);
738
+ };
739
+ }
740
+ function schemaArray(schemaLike, params) {
741
+ return function (schema) {
742
+ return z.preprocess(val => {
743
+ val = coerceWithNil(val);
744
+ if (isNil(val)) return val;
745
+ if (typeof val !== 'string') return val;
746
+ if (isNil(params?.separator) && val[0] === '[') return JSON.parse(val);
747
+ return val.split(params?.separator ?? ',');
748
+ }, z.array(makeSchemaLike(schemaLike ?? schema, z.any()), params)
749
+ // z.array(makeSchemaLike(schemaLike, schema), params),
750
+ );
751
+ };
752
+ }
753
+
754
+ const v = {
755
+ array: schemaArray,
756
+ default: schemaDefault,
757
+ object: schemaObject,
758
+ optional: schemaOptional,
759
+ // helpers
760
+ email: schemaEmail,
761
+ url: schemaUrl,
762
+ uuid: schemaUuid,
763
+ ip: schemaIp,
764
+ min: schemaMin,
765
+ max: schemaMax,
766
+ tableIdentity: schemaTableIdentity,
767
+ // openapi
768
+ openapi: schemaOpenapi,
769
+ title: schemaTitle,
770
+ description: schemaDescription,
771
+ example: schemaExample
772
+ };
773
+
774
+ const OrderCoreBase = 100;
775
+ const OrderBusinessBase = 1000;
776
+ const OrderUnknownBase = 10000;
777
+ const OrderMaxBase = 100000;
778
+
779
+ export { $locale, $schema, Api, Arg, Main, OrderBusinessBase, OrderCoreBase, OrderMaxBase, OrderUnknownBase, ScopeModuleAOpenapi, ServiceOpenapi, SymbolDecoratorRule, SymbolDecoratorRuleColumn, SymbolOpenApiOptions, SymbolRouteHandlersArgumentsMeta, SymbolRouteHandlersArgumentsValue, bodySchemaWrapperDefault, config, createPipesArgumentDecorator, errorsAdapter, getTargetDecoratorRuleColumns, getTargetDecoratorRules, locales, makeSchemaLike, makeSchemaLikes, mergeFieldsOpenAPIMetadata, setPublic, v };