vona-module-a-web 5.0.22 → 5.0.24

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.
@@ -5,25 +5,33 @@ import type { IQueryParams } from 'vona-module-a-orm';
5
5
  import type { ValidatorOptions } from 'vona-module-a-validation';
6
6
  import type z from 'zod';
7
7
  import { BeanBase } from 'vona';
8
+ export type TypePipeQueryData = unknown;
9
+ export type TypePipeQueryResult = TypePipeQueryData;
8
10
  export interface IPipeOptionsQuery extends IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, ValidatorOptions {
9
- transform?: TypePipeOptionsQueryTransform;
11
+ transformFn?: TypePipeOptionsQueryTransform | string;
10
12
  }
13
+ export type TypeQueryParamsPatch = IQueryParams & {
14
+ where: {};
15
+ };
11
16
  export interface IPipeOptionsQueryTransformInfo {
12
- params: IQueryParams;
17
+ params: TypeQueryParamsPatch;
13
18
  query: any;
14
19
  options: IPipeOptionsQuery;
15
20
  originalName: string;
16
21
  fullName: string;
17
- key: string;
18
- value: any;
19
- schema: z.ZodSchema;
22
+ key?: string;
23
+ value?: any;
24
+ schema?: z.ZodType;
20
25
  openapi?: ISchemaObjectExtensionField;
21
26
  }
22
27
  export type TypePipeOptionsQueryTransform = (ctx: VonaContext, info: IPipeOptionsQueryTransformInfo) => boolean | undefined;
23
- export declare class PipeQuery extends BeanBase implements IPipeTransform<any> {
24
- transform(value: any, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsQuery): Promise<any>;
28
+ export declare class PipeQuery extends BeanBase implements IPipeTransform<TypePipeQueryData, TypePipeQueryResult> {
29
+ transform(value: TypePipeQueryData, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsQuery): Promise<TypePipeQueryResult>;
25
30
  private _transform;
26
31
  private _transformSystem;
32
+ private _transformOrders;
33
+ private _transformField;
27
34
  private _transformFields;
35
+ private _performTransformFn;
28
36
  }
29
- export declare const ArgQuery: (options?: Partial<IPipeOptionsQuery> | undefined) => any;
37
+ export declare const ArgQueryPro: (options?: Partial<IPipeOptionsQuery> | undefined) => any;
@@ -2,9 +2,11 @@ import type { IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, IPipeTransfo
2
2
  import type { RouteHandlerArgumentMeta } from 'vona-module-a-openapi';
3
3
  import type { ValidatorOptions } from 'vona-module-a-validation';
4
4
  import { BeanBase } from 'vona';
5
+ export type TypePipeValidData = unknown;
6
+ export type TypePipeValidResult = TypePipeValidData;
5
7
  export interface IPipeOptionsValid extends IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, ValidatorOptions {
6
8
  }
7
- export declare class PipeValid extends BeanBase implements IPipeTransform<any> {
8
- transform(value: any, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsValid): Promise<any>;
9
+ export declare class PipeValid extends BeanBase implements IPipeTransform<TypePipeValidData, TypePipeValidResult> {
10
+ transform(value: TypePipeValidData, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsValid): Promise<TypePipeValidResult>;
9
11
  }
10
12
  export declare const ArgValid: (options?: Partial<IPipeOptionsValid> | undefined) => any;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { HttpStatus, BeanInfo, BeanBase, appMetadata, appResource, deepExtend, compose, cast, BeanSimple, BeanScopeBase, createBeanDecorator } from 'vona';
1
+ import { BeanInfo, BeanBase, cast, appMetadata, appResource, deepExtend, compose, BeanSimple, BeanScopeBase, createBeanDecorator } from 'vona';
2
2
  import { isNil, combineParamsAndQuery } from '@cabloy/utils';
3
- import { ZodMetadata } from '@cabloy/zod-query';
3
+ import { ZodMetadata } from '@cabloy/zod-openapi';
4
4
  import { Pipe, createArgumentPipe, setArgumentPipe } from 'vona-module-a-aspect';
5
5
  import * as ModuleInfo from '@cabloy/module-info';
6
6
  import { Bean, Service, Scope } from 'vona-module-a-bean';
@@ -19,8 +19,8 @@ const __FieldsSystem = ['columns', 'where', 'orders', 'pageNo', 'pageSize'];
19
19
  let PipeQuery = (_dec$5 = Pipe({
20
20
  // ValidatorOptions
21
21
  disableErrorMessages: false,
22
- errorHttpStatusCode: HttpStatus.BAD_REQUEST,
23
- passthrough: false,
22
+ errorHttpStatusCode: 400,
23
+ loose: false,
24
24
  strict: false
25
25
  }), _dec2$5 = BeanInfo({
26
26
  module: "a-web"
@@ -38,7 +38,11 @@ let PipeQuery = (_dec$5 = Pipe({
38
38
  // 1. system: columns/where/orders/pageNo/pageSize
39
39
  const params = this._transformSystem(value);
40
40
  // 2. fields
41
- return this._transformFields(params, value, options);
41
+ this._transformFields(params, value, options);
42
+ // 3. system: orders
43
+ this._transformOrders(params, options);
44
+ // ok
45
+ return params;
42
46
  }
43
47
 
44
48
  // system: columns/where/orders/pageNo/pageSize
@@ -68,75 +72,133 @@ let PipeQuery = (_dec$5 = Pipe({
68
72
  // ok
69
73
  return params;
70
74
  }
71
- _transformFields(params, value, options) {
72
- for (const key in value) {
73
- if (__FieldsSystem.includes(key)) continue;
74
- const fieldSchema = ZodMetadata.unwrapChained(ZodMetadata.getFieldSchema(options.schema, key));
75
- if (!fieldSchema) continue;
76
- // openapi
77
- const openapi = ZodMetadata.getOpenapiMetadata(fieldSchema);
78
- // name
79
- const originalName = openapi?.query?.originalName ?? key;
80
- let fullName;
81
- // joins
82
- if (openapi?.query?.join) {
83
- if (!params.joins) params.joins = [];
84
- const joinType = openapi.query.join.type ?? 'innerJoin';
85
- const joinTable = openapi.query.join.table;
86
- const joinOn = openapi.query.join.on;
87
- if (params.joins.findIndex(item => item[1] === joinTable) === -1) {
88
- params.joins.push([joinType, joinTable, joinOn]);
75
+ _transformOrders(params, options) {
76
+ if (!params.orders) return;
77
+ // openapi
78
+ const openapi = ZodMetadata.getOpenapiMetadata(options.schema);
79
+ const table = openapi?.query?.table;
80
+ // loop
81
+ for (const order of params.orders) {
82
+ const field = order[0];
83
+ if (field.includes('.')) continue;
84
+ let tableCurrent = table;
85
+ let fieldCurrent = field;
86
+ const fieldSchema = ZodMetadata.unwrapChained(ZodMetadata.getFieldSchema(options.schema, field));
87
+ if (fieldSchema) {
88
+ const openapi = ZodMetadata.getOpenapiMetadata(fieldSchema);
89
+ if (openapi?.query?.table) {
90
+ tableCurrent = openapi?.query?.table;
91
+ }
92
+ if (openapi?.query?.originalName) {
93
+ fieldCurrent = openapi?.query?.originalName;
89
94
  }
90
- fullName = `${joinTable}.${originalName}`;
91
- } else {
92
- fullName = originalName;
93
95
  }
94
- // check where
95
- if (params.where[fullName]) continue;
96
- // custom transform
97
- if (options.transform) {
98
- const res = options.transform(this.ctx, {
99
- params,
100
- query: value,
101
- options,
102
- originalName,
103
- fullName,
104
- key,
105
- value: value[key],
106
- schema: fieldSchema,
107
- openapi
108
- });
109
- if (res === true || res === false) continue;
96
+ cast(order)[0] = tableCurrent ? `${tableCurrent}.${fieldCurrent}` : fieldCurrent;
97
+ }
98
+ }
99
+ _transformField(key, fieldValue, params, value, options) {
100
+ if (__FieldsSystem.includes(key)) return;
101
+ const fieldSchema = ZodMetadata.unwrapChained(ZodMetadata.getFieldSchema(options.schema, key));
102
+ if (!fieldSchema) return;
103
+ // openapi
104
+ const openapi = ZodMetadata.getOpenapiMetadata(fieldSchema);
105
+ // name
106
+ const originalName = openapi?.query?.originalName ?? key;
107
+ let fullName;
108
+ // joins
109
+ let joinInfo;
110
+ if (openapi?.query?.joinOn) {
111
+ const joinType = openapi.query.joinType ?? 'innerJoin';
112
+ const joinTable = openapi.query.table;
113
+ const joinOn = openapi.query.joinOn;
114
+ joinInfo = [joinType, joinTable, joinOn];
115
+ fullName = `${joinTable}.${originalName}`;
116
+ } else {
117
+ fullName = originalName;
118
+ }
119
+ // check where
120
+ if (Object.prototype.hasOwnProperty.call(params.where, fullName)) return;
121
+ // custom transform
122
+ const resTransform = this._performTransformFn(options, {
123
+ params,
124
+ query: value,
125
+ options,
126
+ originalName,
127
+ fullName,
128
+ key,
129
+ value: fieldValue,
130
+ schema: fieldSchema,
131
+ openapi
132
+ });
133
+ // res: ignore
134
+ if (resTransform === false) return;
135
+ // join
136
+ if (joinInfo) {
137
+ if (!params.joins) params.joins = [];
138
+ if (params.joins.findIndex(item => item[1] === joinInfo.joinTable) === -1) {
139
+ params.joins.push(joinInfo);
110
140
  }
111
- // default transform
112
- let op = openapi?.query?.op;
113
- if (!op) {
114
- const typeName = fieldSchema._def.typeName;
115
- if (typeName === 'ZodString') {
116
- op = '_includesI_';
117
- } else {
118
- op = '_eq_';
119
- }
141
+ }
142
+ // res: done
143
+ if (resTransform === true) return;
144
+ // default transform
145
+ let op = openapi?.query?.op;
146
+ if (!op) {
147
+ const typeName = fieldSchema.type;
148
+ if (typeName === 'string') {
149
+ op = '_includesI_';
150
+ } else {
151
+ op = '_eq_';
120
152
  }
121
- if (op === '_eq_') {
122
- params.where[fullName] = value[key];
153
+ }
154
+ if (op === '_eq_') {
155
+ params.where[fullName] = fieldValue;
156
+ } else {
157
+ params.where[fullName] = {
158
+ [op]: fieldValue
159
+ };
160
+ }
161
+ }
162
+ _transformFields(params, value, options) {
163
+ // loop
164
+ for (const key in value) {
165
+ this._transformField(key, value[key], params, value, options);
166
+ }
167
+ // custom transform
168
+ this._performTransformFn(options, {
169
+ params,
170
+ query: value,
171
+ options
172
+ });
173
+ }
174
+ _performTransformFn(options, info) {
175
+ if (options.transformFn) {
176
+ if (typeof options.transformFn === 'string') {
177
+ const controller = this.ctx.getControllerBean();
178
+ if (!controller[options.transformFn]) {
179
+ throw new Error(`transformFn not found: ${this.ctx.getControllerBeanFullName()}`);
180
+ }
181
+ return controller[options.transformFn](info);
123
182
  } else {
124
- params.where[fullName] = {
125
- [op]: value[key]
126
- };
183
+ return options.transformFn(this.ctx, info);
184
+ }
185
+ } else {
186
+ const controller = this.ctx.getControllerBean();
187
+ const transformFn = `${String(this.ctx.getHandlerName())}QueryTransform`;
188
+ if (controller[transformFn]) {
189
+ return controller[transformFn](info);
127
190
  }
128
191
  }
129
- return params;
130
192
  }
131
193
  }) || _class$5) || _class$5);
132
- const ArgQuery = createArgumentPipe('a-web:query');
194
+ const ArgQueryPro$1 = createArgumentPipe('a-web:query');
133
195
 
134
196
  var _dec$4, _dec2$4, _class$4;
135
197
  let PipeValid = (_dec$4 = Pipe({
136
198
  // ValidatorOptions
137
199
  disableErrorMessages: false,
138
- errorHttpStatusCode: HttpStatus.BAD_REQUEST,
139
- passthrough: false,
200
+ errorHttpStatusCode: 400,
201
+ loose: false,
140
202
  strict: false
141
203
  }), _dec2$4 = BeanInfo({
142
204
  module: "a-web"
@@ -219,8 +281,6 @@ async function middlewarePipe(ctx, next) {
219
281
  // check handler
220
282
  const handler = ctx.getHandler();
221
283
  if (!handler) return next();
222
- // body parser
223
- await ctx.app.bean._getBean('a-body.service.body').parse(true);
224
284
  // arguments
225
285
  ctx[SymbolRouteHandlersArgumentsValue] = await _transformArguments(ctx, ctx.getController(), handler);
226
286
  // next
@@ -260,6 +320,7 @@ async function _transformArguments(ctx, controller, handler) {
260
320
  async function _transformArgument(ctx, argMeta, metadata, value) {
261
321
  // pipes
262
322
  const pipes = composePipes(ctx, argMeta, (beanInstance, value, options, _next) => {
323
+ if (!isNil(options.argIndex) && argMeta.index !== options.argIndex) return value;
263
324
  return beanInstance.transform(value, metadata, options);
264
325
  });
265
326
  if (pipes.length === 0) return value;
@@ -444,24 +505,23 @@ let BeanRouter = (_dec$3 = Bean(), _dec2$3 = BeanInfo({
444
505
  }
445
506
  }) || _class$3) || _class$3);
446
507
  function classControllerMiddleware(ctx) {
447
- const beanFullName = ctx.getControllerBeanFullName();
448
- const handlerName = ctx.getHandler().name;
449
- const controller = ctx.app.bean._getBean(beanFullName);
508
+ const handlerName = ctx.getHandlerName();
509
+ const controller = ctx.getControllerBean();
450
510
  return controller[handlerName](...(ctx[SymbolRouteHandlersArgumentsValue] || []));
451
511
  }
452
512
  async function routeStartMiddleware(ctx, next) {
453
513
  // next
454
514
  const res = await next();
455
- // invoke callbackes: handle secondly
456
- await ctx.commitDone();
515
+ // invoke callbacks: handle secondly
516
+ await ctx.commitsDone();
457
517
  // ok
458
518
  return res;
459
519
  }
460
520
  async function routeTailDoneMiddleware(ctx, next) {
461
521
  // next
462
522
  const res = await next();
463
- // invoke callbackes: handle firstly
464
- await ctx.commitDone();
523
+ // invoke callbacks: handle firstly
524
+ await ctx.commitsDone();
465
525
  // ok
466
526
  return res;
467
527
  }
@@ -478,7 +538,7 @@ async function routeTailDoneMiddleware(ctx, next) {
478
538
  // // next
479
539
  // const res = await next();
480
540
  // // invoke callbackes: handle secondly
481
- // await ctx.commitDone();
541
+ // await ctx.commitsDone();
482
542
  // // ok
483
543
  // return res;
484
544
  // };
@@ -497,7 +557,7 @@ async function routeTailDoneMiddleware(ctx, next) {
497
557
  // // next
498
558
  // const res = await next();
499
559
  // // invoke callbackes: handle firstly
500
- // await ctx.commitDone();
560
+ // await ctx.commitsDone();
501
561
  // // ok
502
562
  // return res;
503
563
  // };
@@ -706,12 +766,13 @@ function File(property, ...schemaLikes) {
706
766
  function User(...schemaLikes) {
707
767
  return createPipesArgumentDecorator('user')(undefined, ...schemaLikes);
708
768
  }
709
- function ArgQueryPro(schemaLike) {
769
+ function ArgQueryPro(schemaLike, transformFn) {
710
770
  return function (target, prop, index) {
711
771
  const schema = $schema(schemaLike);
712
772
  setArgumentPipe('a-web:query', {
713
773
  type: 'query',
714
- schema
774
+ schema,
775
+ transformFn
715
776
  }, target, prop, index);
716
777
  };
717
778
  }
@@ -825,4 +886,4 @@ function $apiPathAndCombineParamsAndQuery(path, options) {
825
886
  return combineParamsAndQuery(path, options);
826
887
  }
827
888
 
828
- export { $apiPath, $apiPathAndCombineParamsAndQuery, Arg, ArgQuery, ArgValid, BeanRouter, Controller, Dto, Main, PipeQuery, PipeValid, RequestMapping, ScopeModuleAWeb, ServiceWeb, StartupListen, SymbolRequestMappingHandler, Web, config, createPipesArgumentDecorator, mergeActionsOpenapiMetadata };
889
+ export { $apiPath, $apiPathAndCombineParamsAndQuery, Arg, ArgQueryPro$1 as ArgQueryPro, ArgValid, BeanRouter, Controller, Dto, Main, PipeQuery, PipeValid, RequestMapping, ScopeModuleAWeb, ServiceWeb, StartupListen, SymbolRequestMappingHandler, Web, config, createPipesArgumentDecorator, mergeActionsOpenapiMetadata };
@@ -1,6 +1,7 @@
1
1
  import type { Constructable } from 'vona';
2
2
  import type { SchemaLike } from 'vona-module-a-openapiutils';
3
3
  import type z from 'zod';
4
+ import type { TypePipeOptionsQueryTransform } from '../../bean/pipe.query.ts';
4
5
  declare function Param(): ParameterDecorator;
5
6
  declare function Param(...schemaLikes: SchemaLike[]): ParameterDecorator;
6
7
  declare function Param(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
@@ -26,7 +27,7 @@ declare function File(): ParameterDecorator;
26
27
  declare function File(...schemaLikes: SchemaLike[]): ParameterDecorator;
27
28
  declare function File(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
28
29
  declare function User(...schemaLikes: SchemaLike[]): ParameterDecorator;
29
- declare function ArgQueryPro(schemaLike: z.ZodSchema | Constructable): any;
30
+ declare function ArgQueryPro(schemaLike: z.ZodType | Constructable, transformFn?: TypePipeOptionsQueryTransform | string): any;
30
31
  export declare const Arg: {
31
32
  param: typeof Param;
32
33
  query: typeof Query;
@@ -28,7 +28,7 @@ export interface IDecoratorControllerOptions extends TypeOnionOptionsEnableSimpl
28
28
  }
29
29
  declare module 'vona-module-a-onion' {
30
30
  interface BeanOnion {
31
- controller: ServiceOnion<IDecoratorControllerOptions, keyof IControllerRecord>;
31
+ controller: ServiceOnion<IControllerRecord>;
32
32
  }
33
33
  }
34
34
  declare module 'vona' {
@@ -1,6 +1,7 @@
1
1
  import type { OmitNever } from 'vona';
2
2
  import type { ServiceOnion } from 'vona-module-a-onion';
3
3
  import type { TypeOpenapiMetadata } from 'vona-module-a-openapi';
4
+ import type { SchemaLike } from 'vona-module-a-openapiutils';
4
5
  import type { SymbolKeyFieldsMore } from 'vona-module-a-orm';
5
6
  export interface IDtoRecord {
6
7
  }
@@ -8,10 +9,11 @@ export interface IDecoratorDtoOptions<FieldsMore = never> {
8
9
  [SymbolKeyFieldsMore]?: FieldsMore;
9
10
  independent?: boolean;
10
11
  openapi?: TypeOpenapiMetadata;
12
+ pipes?: SchemaLike | SchemaLike[];
11
13
  }
12
14
  declare module 'vona-module-a-onion' {
13
15
  interface BeanOnion {
14
- dto: ServiceOnion<IDecoratorDtoOptions, keyof IDtoRecord>;
16
+ dto: ServiceOnion<IDtoRecord>;
15
17
  }
16
18
  }
17
19
  declare module 'vona' {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vona-module-a-web",
3
3
  "type": "module",
4
- "version": "5.0.22",
4
+ "version": "5.0.24",
5
5
  "title": "a-web",
6
6
  "vonaModule": {
7
7
  "capabilities": {