vona-module-a-openapi 5.0.24 → 5.0.26

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.
@@ -9,6 +9,10 @@ declare module 'vona-module-a-bean' {
9
9
  declare module 'vona-module-a-openapi' {
10
10
  interface ServiceOpenapi {
11
11
  }
12
+ interface ServiceOpenapi {
13
+ get $beanFullName(): 'a-openapi.service.openapi';
14
+ get $onionName(): 'a-openapi:openapi';
15
+ }
12
16
  }
13
17
  /** service: end */
14
18
  /** service: begin */
@@ -36,6 +40,10 @@ declare module 'vona-module-a-summer' {
36
40
  declare module 'vona-module-a-openapi' {
37
41
  interface SummerCacheJson {
38
42
  }
43
+ interface SummerCacheJson {
44
+ get $beanFullName(): 'a-openapi.summerCache.json';
45
+ get $onionName(): 'a-openapi:json';
46
+ }
39
47
  }
40
48
  /** summerCache: end */
41
49
  /** summerCache: begin */
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- import { appMetadata, appResource, cast, BeanInfo, BeanBase, LocaleModuleNameSeparator, HttpStatus, BeanSimple, BeanScopeBase, isClassStrict, registerMappedClassMetadataKey, deepExtend } from 'vona';
1
+ import { registerMappedClassMetadataKey, appMetadata, appResource, cast, deepExtend, BeanInfo, BeanBase, LocaleModuleNameSeparator, HttpStatus, BeanSimple, BeanScopeBase } from 'vona';
2
2
  import { OpenApiGeneratorV3, OpenApiGeneratorV31, OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
3
3
  import * as ModuleInfo from '@cabloy/module-info';
4
- import { isEmptyObject, isNil } from '@cabloy/utils';
4
+ import { isClass, isEmptyObject, isNil } from '@cabloy/utils';
5
5
  import { toUpperCaseFirstChar } from '@cabloy/word-utils';
6
- import { getTypeName, coerceWithNil } from '@cabloy/zod-query';
6
+ import { getTypeName, ZodMetadata, coerceWithNil } from '@cabloy/zod-query';
7
7
  import { Service, Scope } from 'vona-module-a-bean';
8
8
  import { Caching } from 'vona-module-a-caching';
9
- import { SymbolDecoratorRule, SymbolOpenApiOptions, SymbolDecoratorRuleColumn } from 'vona-module-a-openapiutils';
9
+ import { SymbolDecoratorRule, SymbolDecoratorRuleColumn, SymbolOpenApiOptions } from 'vona-module-a-openapiutils';
10
10
  import { SymbolRequestMappingHandler } from 'vona-module-a-web';
11
11
  import { z } from 'zod';
12
12
  import { SummerCache, BeanSummerCacheBase } from 'vona-module-a-summer';
@@ -31,6 +31,82 @@ function bodySchemaWrapperDefault(bodySchema) {
31
31
  });
32
32
  }
33
33
 
34
+ function getTargetDecoratorRules(target) {
35
+ registerMappedClassMetadataKey(target, SymbolDecoratorRule, {
36
+ partialClass: meta => {
37
+ return meta.optional();
38
+ }
39
+ });
40
+ return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRule, target);
41
+ }
42
+ function getTargetDecoratorRuleColumns(target) {
43
+ registerMappedClassMetadataKey(target, SymbolDecoratorRuleColumn);
44
+ return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRuleColumn, target);
45
+ }
46
+ function mergeFieldsOpenapiMetadata(target) {
47
+ // rules
48
+ const rules = getTargetDecoratorRules(target.prototype);
49
+ // beanOptions
50
+ const beanOptions = appResource.getBean(target);
51
+ const fields = cast(beanOptions?.options)?.fields;
52
+ if (!fields) return;
53
+ for (const key in fields) {
54
+ const field = fields[key];
55
+ if (!field) continue;
56
+ const schemaCurrent = rules[key];
57
+ if (Object.prototype.hasOwnProperty.call(field, 'parseAsync')) {
58
+ const schema = field;
59
+ rules[key] = schema.openapi(deepExtend({}, schemaCurrent?._def.openapi?.metadata, schema._def.openapi?.metadata));
60
+ } else {
61
+ // use deepExtend for sure strict
62
+ if (schemaCurrent) {
63
+ rules[key] = schemaCurrent.openapi(deepExtend({}, schemaCurrent._def.openapi?.metadata, field));
64
+ } else {
65
+ rules[key] = z.any().openapi(deepExtend({}, field));
66
+ }
67
+ }
68
+ }
69
+ }
70
+ function prepareClassType(classType) {
71
+ return isClass(classType) ? classType : cast(classType)();
72
+ }
73
+
74
+ function makeSchemaLikes(schemaLikes, typeInit) {
75
+ // default schema
76
+ let argSchema = $schema(typeInit);
77
+ // loop
78
+ for (let index = schemaLikes.length - 1; index >= 0; index--) {
79
+ const schemaLike = schemaLikes[index];
80
+ argSchema = makeSchemaLike(schemaLike, argSchema);
81
+ }
82
+ return argSchema;
83
+ }
84
+ function makeSchemaLike(schemaLike, schemaPrevious) {
85
+ if (!schemaLike) return schemaPrevious;
86
+ if (Object.prototype.hasOwnProperty.call(schemaLike, 'parseAsync')) {
87
+ // schema
88
+ return schemaLike;
89
+ } else if (isClass(schemaLike) || ['String', 'Number', 'Boolean', 'Date', 'BigInt', 'Array'].includes(cast(schemaLike).name)) {
90
+ // class
91
+ return $schema(cast(schemaLike));
92
+ } else {
93
+ // function
94
+ return cast(schemaLike)(schemaPrevious);
95
+ }
96
+ }
97
+
98
+ const __schemasDynamic = {};
99
+ const SymbolSchemaDynamicRefId = Symbol('SymbolSchemaDynamicRefId');
100
+ function addSchemaDynamic(dynamicName, classType) {
101
+ __schemasDynamic[dynamicName] = classType;
102
+ }
103
+ function getSchemaDynamic(dynamicName) {
104
+ return __schemasDynamic[dynamicName];
105
+ }
106
+ function getSchemasDynamic() {
107
+ return __schemasDynamic;
108
+ }
109
+
34
110
  function $schema(classType, options) {
35
111
  if (!classType) return z.any();
36
112
  if (classType.parseAsync) return classType;
@@ -47,15 +123,37 @@ function $schema(classType, options) {
47
123
  return z.any();
48
124
  }
49
125
  // object
126
+ let schema = _createSchemaObject(rules, options);
127
+ // refId
128
+ const schemaDynamicRefId = classType[SymbolSchemaDynamicRefId];
129
+ if (schemaDynamicRefId) {
130
+ // dynamic
131
+ schema = schema.openapi(schemaDynamicRefId);
132
+ } else {
133
+ // static
134
+ const beanOptions = appResource.getBean(classType);
135
+ if (beanOptions) {
136
+ const openapi = cast(beanOptions.options)?.openapi;
137
+ schema = schema.openapi(beanOptions.beanFullName, openapi);
138
+ }
139
+ }
140
+ return schema;
141
+ }
142
+ function $schemaLazy(...schemaLikes) {
143
+ return z.lazy(() => {
144
+ return _createSchemaLazy(schemaLikes);
145
+ });
146
+ }
147
+ function _createSchemaLazy(schemaLikes) {
148
+ const classType = schemaLikes[schemaLikes.length - 1];
149
+ schemaLikes = schemaLikes.slice(0, schemaLikes.length - 1);
150
+ const classType2 = prepareClassType(classType);
151
+ return makeSchemaLikes(schemaLikes, $schema(classType2));
152
+ }
153
+ function _createSchemaObject(rules, options) {
50
154
  let schema = z.object(rules);
51
155
  if (options?.passthrough) schema = schema.passthrough();
52
156
  if (options?.strict) schema = schema.strict();
53
- // refId
54
- const beanOptions = appResource.getBean(classType);
55
- if (beanOptions) {
56
- const openapi = cast(beanOptions.options)?.openapi;
57
- schema = schema.openapi(beanOptions.beanFullName, openapi);
58
- }
59
157
  return schema;
60
158
  }
61
159
 
@@ -404,7 +502,9 @@ let ServiceOpenapi = (_dec$2 = Service(), _dec2$2 = BeanInfo({
404
502
  }, _applyDecoratedDescriptor(_class2.prototype, "generateJson", [_dec3, _dec4, _dec5], Object.getOwnPropertyDescriptor(_class2.prototype, "generateJson"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "generateJsonOfControllerAction", [_dec6, _dec7, _dec8], Object.getOwnPropertyDescriptor(_class2.prototype, "generateJsonOfControllerAction"), _class2.prototype), _class2)) || _class$2) || _class$2);
405
503
 
406
504
  var _dec$1, _dec2$1, _class$1;
407
- let SummerCacheJson = (_dec$1 = SummerCache(), _dec2$1 = BeanInfo({
505
+ let SummerCacheJson = (_dec$1 = SummerCache({
506
+ preset: 'mem'
507
+ }), _dec2$1 = BeanInfo({
408
508
  module: "a-openapi"
409
509
  }), _dec$1(_class$1 = _dec2$1(_class$1 = class SummerCacheJson extends BeanSummerCacheBase {
410
510
  async getNative(_key, _options) {}
@@ -454,10 +554,39 @@ function errorsAdapter(app) {
454
554
  });
455
555
  }
456
556
 
557
+ function schemaRefCustomAdapter(_app) {
558
+ const registry = new OpenAPIRegistry();
559
+ const generator31 = new OpenApiGeneratorV31(registry.definitions);
560
+ _patchGenerator(generator31);
561
+ }
562
+ function _patchGenerator(generator) {
563
+ const gen = Object.getPrototypeOf(cast(generator).generator);
564
+ gen.generateSchemaWithRef = function (zodSchema) {
565
+ // schema ref
566
+ const lazySchema = ZodMetadata.getLazySchema(zodSchema);
567
+ if (lazySchema) {
568
+ zodSchema = lazySchema();
569
+ }
570
+ const refId = ZodMetadata.getRefId(zodSchema);
571
+ if (!refId) {
572
+ return this.generateSimpleSchema(zodSchema);
573
+ }
574
+ if (this.schemaRefs[refId] === undefined) {
575
+ this.schemaRefs[refId] = null;
576
+ const result = this.generateSimpleSchema(zodSchema);
577
+ this.schemaRefs[refId] = result;
578
+ }
579
+ return {
580
+ $ref: this.generateSchemaRef(refId)
581
+ };
582
+ };
583
+ }
584
+
457
585
  class Main extends BeanSimple {
458
586
  async moduleLoading() {}
459
587
  async moduleLoaded() {
460
588
  errorsAdapter(this.app);
589
+ schemaRefCustomAdapter(this.app);
461
590
  }
462
591
  async configLoaded(_config) {}
463
592
  }
@@ -475,67 +604,6 @@ function $locale(key) {
475
604
  }
476
605
  /** scope: end */
477
606
 
478
- function makeSchemaLikes(schemaLikes, typeInit) {
479
- // default schema
480
- let argSchema = $schema(typeInit);
481
- // loop
482
- for (let index = schemaLikes.length - 1; index >= 0; index--) {
483
- const schemaLike = schemaLikes[index];
484
- argSchema = makeSchemaLike(schemaLike, argSchema);
485
- }
486
- return argSchema;
487
- }
488
- function makeSchemaLike(schemaLike, schemaPrevious) {
489
- if (!schemaLike) return schemaPrevious;
490
- if (Object.prototype.hasOwnProperty.call(schemaLike, 'parseAsync')) {
491
- // schema
492
- return schemaLike;
493
- } else if (isClassStrict(schemaLike) || ['String', 'Number', 'Boolean', 'Date', 'BigInt', 'Array'].includes(cast(schemaLike).name)) {
494
- // class
495
- return $schema(cast(schemaLike));
496
- } else {
497
- // function
498
- return cast(schemaLike)(schemaPrevious);
499
- }
500
- }
501
-
502
- function getTargetDecoratorRules(target) {
503
- registerMappedClassMetadataKey(target, SymbolDecoratorRule, {
504
- partialClass: meta => {
505
- return meta.optional();
506
- }
507
- });
508
- return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRule, target);
509
- }
510
- function getTargetDecoratorRuleColumns(target) {
511
- registerMappedClassMetadataKey(target, SymbolDecoratorRuleColumn);
512
- return appMetadata.getOwnMetadataMap(true, SymbolDecoratorRuleColumn, target);
513
- }
514
- function mergeFieldsOpenapiMetadata(target) {
515
- // rules
516
- const rules = getTargetDecoratorRules(target.prototype);
517
- // beanOptions
518
- const beanOptions = appResource.getBean(target);
519
- const fields = cast(beanOptions?.options)?.fields;
520
- if (!fields) return;
521
- for (const key in fields) {
522
- const field = fields[key];
523
- if (!field) continue;
524
- const schemaCurrent = rules[key];
525
- if (Object.prototype.hasOwnProperty.call(field, 'parseAsync')) {
526
- const schema = field;
527
- rules[key] = schema.openapi(deepExtend({}, schemaCurrent?._def.openapi?.metadata, schema._def.openapi?.metadata));
528
- } else {
529
- // use deepExtend for sure strict
530
- if (schemaCurrent) {
531
- rules[key] = schemaCurrent.openapi(deepExtend({}, schemaCurrent._def.openapi?.metadata, field));
532
- } else {
533
- rules[key] = z.any().openapi(deepExtend({}, field));
534
- }
535
- }
536
- }
537
- }
538
-
539
607
  function Field$1(...schemaLikes) {
540
608
  return function (target, prop) {
541
609
  // rules
@@ -749,6 +817,11 @@ function schemaTableIdentity() {
749
817
  return z.union([z.string(), z.number()]);
750
818
  };
751
819
  }
820
+ function schemaBigNumber() {
821
+ return function (_schema) {
822
+ return z.union([z.string(), z.number()]);
823
+ };
824
+ }
752
825
 
753
826
  function schemaOpenapi(refId, metadata) {
754
827
  return function (schema) {
@@ -787,6 +860,11 @@ function schemaOptional() {
787
860
  return schema.optional();
788
861
  };
789
862
  }
863
+ function schemaLazy(...schemaLikes) {
864
+ return function (_schema) {
865
+ return $schemaLazy(...schemaLikes);
866
+ };
867
+ }
790
868
  function schemaObject(classType, options) {
791
869
  return function (_schema) {
792
870
  return $schema(classType, options);
@@ -807,6 +885,7 @@ function schemaArray(schemaLike, params) {
807
885
  }
808
886
 
809
887
  const v = {
888
+ lazy: schemaLazy,
810
889
  array: schemaArray,
811
890
  default: schemaDefault,
812
891
  object: schemaObject,
@@ -819,6 +898,7 @@ const v = {
819
898
  min: schemaMin,
820
899
  max: schemaMax,
821
900
  tableIdentity: schemaTableIdentity,
901
+ bigNumber: schemaBigNumber,
822
902
  // openapi
823
903
  openapi: schemaOpenapi,
824
904
  title: schemaTitle,
@@ -831,4 +911,4 @@ const OrderBusinessBase = 1000;
831
911
  const OrderUnknownBase = 10000;
832
912
  const OrderMaxBase = 100000;
833
913
 
834
- export { $locale, $schema, Api, Arg, Main, OrderBusinessBase, OrderCoreBase, OrderMaxBase, OrderUnknownBase, ScopeModuleAOpenapi, ServiceOpenapi, SummerCacheJson, SymbolRouteHandlersArgumentsMeta, SymbolRouteHandlersArgumentsValue, bodySchemaWrapperDefault, config, createPipesArgumentDecorator, errorsAdapter, getTargetDecoratorRuleColumns, getTargetDecoratorRules, locales, makeSchemaLike, makeSchemaLikes, mergeFieldsOpenapiMetadata, v };
914
+ export { $locale, $schema, $schemaLazy, Api, Arg, Main, OrderBusinessBase, OrderCoreBase, OrderMaxBase, OrderUnknownBase, ScopeModuleAOpenapi, ServiceOpenapi, SummerCacheJson, SymbolRouteHandlersArgumentsMeta, SymbolRouteHandlersArgumentsValue, SymbolSchemaDynamicRefId, addSchemaDynamic, bodySchemaWrapperDefault, config, createPipesArgumentDecorator, errorsAdapter, getSchemaDynamic, getSchemasDynamic, getTargetDecoratorRuleColumns, getTargetDecoratorRules, locales, makeSchemaLike, makeSchemaLikes, mergeFieldsOpenapiMetadata, prepareClassType, schemaRefCustomAdapter, v };
@@ -1,4 +1,5 @@
1
1
  export * from './bodySchemaWrapper.ts';
2
2
  export * from './makeSchemaLikes.ts';
3
3
  export * from './schema.ts';
4
+ export * from './schemaDynamic.ts';
4
5
  export * from './v.ts';
@@ -1,4 +1,5 @@
1
1
  import type { Constructable } from 'vona';
2
+ import type { SchemaLike } from 'vona-module-a-openapiutils';
2
3
  import type { ISchemaObjectOptions } from '../../types/decorator.ts';
3
4
  import { z } from 'zod';
4
5
  export declare function $schema(schemaLike: z.ZodSchema): z.ZodSchema;
@@ -9,3 +10,4 @@ export declare function $schema(classType: DateConstructor): z.ZodDate;
9
10
  export declare function $schema(classType: BigIntConstructor): z.ZodBigInt;
10
11
  export declare function $schema(classType: ArrayConstructor): z.ZodArray<z.ZodAny>;
11
12
  export declare function $schema<T>(classType: Constructable<T>, options?: ISchemaObjectOptions): z.ZodSchema<T>;
13
+ export declare function $schemaLazy<T>(...schemaLikes: SchemaLike[]): z.ZodSchema<T>;
@@ -0,0 +1,5 @@
1
+ import type { Constructable } from 'vona';
2
+ export declare const SymbolSchemaDynamicRefId: unique symbol;
3
+ export declare function addSchemaDynamic(dynamicName: string, classType: Constructable): void;
4
+ export declare function getSchemaDynamic(dynamicName: string): Constructable;
5
+ export declare function getSchemasDynamic(): Record<string, Constructable>;
@@ -11,3 +11,4 @@ export declare function schemaIp(options?: string | {
11
11
  export declare function schemaMin(min: number, message?: errorUtil.ErrMessage): (schema: any) => any;
12
12
  export declare function schemaMax(max: number, message?: errorUtil.ErrMessage): (schema: any) => any;
13
13
  export declare function schemaTableIdentity(): (_schema: any) => any;
14
+ export declare function schemaBigNumber(): (_schema: any) => any;
@@ -2,9 +2,10 @@ import type { Constructable } from 'vona';
2
2
  import type { SchemaLike } from 'vona-module-a-openapiutils';
3
3
  import type { ISchemaObjectOptions } from '../../../types/decorator.ts';
4
4
  import { z } from 'zod';
5
- export declare function schemaDefault<T>(defaultValue: T): (schema: z.ZodSchema) => z.ZodSchema;
5
+ export declare function schemaDefault(defaultValue: any | Function): (schema: z.ZodSchema) => z.ZodSchema;
6
6
  export declare function schemaOptional(): (schema: z.ZodSchema) => z.ZodSchema;
7
- export declare function schemaObject<T>(classType: Constructable<T>, options?: ISchemaObjectOptions): (_schema: z.ZodSchema) => z.ZodSchema<T>;
7
+ export declare function schemaLazy<T>(...schemaLikes: SchemaLike[]): (_schema?: z.ZodSchema) => z.ZodSchema<T>;
8
+ export declare function schemaObject<T>(classType: Constructable<T>, options?: ISchemaObjectOptions): (_schema?: z.ZodSchema) => z.ZodSchema<T>;
8
9
  export declare function schemaArray(schemaLike?: SchemaLike, params?: z.RawCreateParams & {
9
10
  separator?: string;
10
11
  }): (schema: z.ZodSchema) => z.ZodSchema;
@@ -1,7 +1,8 @@
1
- import { schemaEmail, schemaIp, schemaMax, schemaMin, schemaTableIdentity, schemaUrl, schemaUuid } from './v/helpers.ts';
1
+ import { schemaBigNumber, schemaEmail, schemaIp, schemaMax, schemaMin, schemaTableIdentity, schemaUrl, schemaUuid } from './v/helpers.ts';
2
2
  import { schemaDescription, schemaExample, schemaOpenapi, schemaTitle } from './v/openapi.ts';
3
- import { schemaArray, schemaDefault, schemaObject, schemaOptional } from './v/system.ts';
3
+ import { schemaArray, schemaDefault, schemaLazy, schemaObject, schemaOptional } from './v/system.ts';
4
4
  export declare const v: {
5
+ lazy: typeof schemaLazy;
5
6
  array: typeof schemaArray;
6
7
  default: typeof schemaDefault;
7
8
  object: typeof schemaObject;
@@ -13,6 +14,7 @@ export declare const v: {
13
14
  min: typeof schemaMin;
14
15
  max: typeof schemaMax;
15
16
  tableIdentity: typeof schemaTableIdentity;
17
+ bigNumber: typeof schemaBigNumber;
16
18
  openapi: typeof schemaOpenapi;
17
19
  title: typeof schemaTitle;
18
20
  description: typeof schemaDescription;
@@ -2,3 +2,4 @@ import type { Constructable } from 'vona';
2
2
  export declare function getTargetDecoratorRules(target: object): Record<PropertyKey, unknown>;
3
3
  export declare function getTargetDecoratorRuleColumns(target: object): Record<PropertyKey, unknown>;
4
4
  export declare function mergeFieldsOpenapiMetadata(target: Constructable): void;
5
+ export declare function prepareClassType<T>(classType: (() => Constructable<T>) | Constructable<T>): Constructable<T>;
@@ -1,2 +1,3 @@
1
1
  export * from './errorsAdapter.ts';
2
2
  export * from './errorUtil.ts';
3
+ export * from './schemaRefCustomAdapter.ts';
@@ -0,0 +1,2 @@
1
+ import type { VonaApplication } from 'vona';
2
+ export declare function schemaRefCustomAdapter(_app: VonaApplication): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vona-module-a-openapi",
3
3
  "type": "module",
4
- "version": "5.0.24",
4
+ "version": "5.0.26",
5
5
  "title": "a-openapi",
6
6
  "vonaModule": {
7
7
  "capabilities": {
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@asteasolutions/zod-to-openapi": "^7.3.0",
37
37
  "@cabloy/zod-errors-custom": "^1.0.13",
38
- "@cabloy/zod-query": "^1.0.15",
38
+ "@cabloy/zod-query": "^1.0.16",
39
39
  "@zhennann/currency": "^2.0.0",
40
40
  "openapi3-ts": "^4.4.0",
41
41
  "zod": "^3.25.58"