vona-module-a-web 5.0.21 → 5.0.23
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/.metadata/index.d.ts +27 -0
- package/dist/bean/pipe.query.d.ts +37 -0
- package/dist/bean/pipe.valid.d.ts +12 -0
- package/dist/index.js +297 -22
- package/dist/lib/decorator/arguments.d.ts +43 -0
- package/dist/lib/decorator/index.d.ts +2 -0
- package/dist/lib/decorator/pipesArgument.d.ts +3 -0
- package/dist/types/controller.d.ts +1 -1
- package/dist/types/dto.d.ts +3 -1
- package/package.json +1 -1
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/** pipe: begin */
|
|
2
|
+
export * from '../bean/pipe.query.ts';
|
|
3
|
+
export * from '../bean/pipe.valid.ts';
|
|
4
|
+
import type { IPipeOptionsQuery } from '../bean/pipe.query.ts';
|
|
5
|
+
import type { IPipeOptionsValid } from '../bean/pipe.valid.ts';
|
|
6
|
+
import 'vona';
|
|
7
|
+
declare module 'vona-module-a-aspect' {
|
|
8
|
+
interface IPipeRecordLocal {
|
|
9
|
+
'a-web:query': IPipeOptionsQuery;
|
|
10
|
+
'a-web:valid': IPipeOptionsValid;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
declare module 'vona-module-a-web' {
|
|
14
|
+
interface PipeQuery {
|
|
15
|
+
}
|
|
16
|
+
interface PipeQuery {
|
|
17
|
+
get $beanFullName(): 'a-web.pipe.query';
|
|
18
|
+
get $onionName(): 'a-web:query';
|
|
19
|
+
}
|
|
20
|
+
interface PipeValid {
|
|
21
|
+
}
|
|
22
|
+
interface PipeValid {
|
|
23
|
+
get $beanFullName(): 'a-web.pipe.valid';
|
|
24
|
+
get $onionName(): 'a-web:valid';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** pipe: end */
|
|
1
28
|
/** bean: begin */
|
|
2
29
|
export * from '../bean/bean.router.ts';
|
|
3
30
|
import 'vona';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { VonaContext } from 'vona';
|
|
2
|
+
import type { IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, IPipeTransform } from 'vona-module-a-aspect';
|
|
3
|
+
import type { ISchemaObjectExtensionField, RouteHandlerArgumentMeta } from 'vona-module-a-openapi';
|
|
4
|
+
import type { IQueryParams } from 'vona-module-a-orm';
|
|
5
|
+
import type { ValidatorOptions } from 'vona-module-a-validation';
|
|
6
|
+
import type z from 'zod';
|
|
7
|
+
import { BeanBase } from 'vona';
|
|
8
|
+
export type TypePipeQueryData = unknown;
|
|
9
|
+
export type TypePipeQueryResult = TypePipeQueryData;
|
|
10
|
+
export interface IPipeOptionsQuery extends IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, ValidatorOptions {
|
|
11
|
+
transformFn?: TypePipeOptionsQueryTransform | string;
|
|
12
|
+
}
|
|
13
|
+
export type TypeQueryParamsPatch = IQueryParams & {
|
|
14
|
+
where: {};
|
|
15
|
+
};
|
|
16
|
+
export interface IPipeOptionsQueryTransformInfo {
|
|
17
|
+
params: TypeQueryParamsPatch;
|
|
18
|
+
query: any;
|
|
19
|
+
options: IPipeOptionsQuery;
|
|
20
|
+
originalName: string;
|
|
21
|
+
fullName: string;
|
|
22
|
+
key?: string;
|
|
23
|
+
value?: any;
|
|
24
|
+
schema?: z.ZodType;
|
|
25
|
+
openapi?: ISchemaObjectExtensionField;
|
|
26
|
+
}
|
|
27
|
+
export type TypePipeOptionsQueryTransform = (ctx: VonaContext, info: IPipeOptionsQueryTransformInfo) => boolean | undefined;
|
|
28
|
+
export declare class PipeQuery extends BeanBase implements IPipeTransform<TypePipeQueryData, TypePipeQueryResult> {
|
|
29
|
+
transform(value: TypePipeQueryData, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsQuery): Promise<TypePipeQueryResult>;
|
|
30
|
+
private _transform;
|
|
31
|
+
private _transformSystem;
|
|
32
|
+
private _transformOrders;
|
|
33
|
+
private _transformField;
|
|
34
|
+
private _transformFields;
|
|
35
|
+
private _performTransformFn;
|
|
36
|
+
}
|
|
37
|
+
export declare const ArgQueryPro: (options?: Partial<IPipeOptionsQuery> | undefined) => any;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, IPipeTransform } from 'vona-module-a-aspect';
|
|
2
|
+
import type { RouteHandlerArgumentMeta } from 'vona-module-a-openapi';
|
|
3
|
+
import type { ValidatorOptions } from 'vona-module-a-validation';
|
|
4
|
+
import { BeanBase } from 'vona';
|
|
5
|
+
export type TypePipeValidData = unknown;
|
|
6
|
+
export type TypePipeValidResult = TypePipeValidData;
|
|
7
|
+
export interface IPipeOptionsValid extends IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, ValidatorOptions {
|
|
8
|
+
}
|
|
9
|
+
export declare class PipeValid extends BeanBase implements IPipeTransform<TypePipeValidData, TypePipeValidResult> {
|
|
10
|
+
transform(value: TypePipeValidData, metadata: RouteHandlerArgumentMeta, options: IPipeOptionsValid): Promise<TypePipeValidResult>;
|
|
11
|
+
}
|
|
12
|
+
export declare const ArgValid: (options?: Partial<IPipeOptionsValid> | undefined) => any;
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,217 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HttpStatus, BeanInfo, BeanBase, cast, appMetadata, appResource, deepExtend, compose, BeanSimple, BeanScopeBase, createBeanDecorator } from 'vona';
|
|
2
|
+
import { isNil, combineParamsAndQuery } from '@cabloy/utils';
|
|
3
|
+
import { ZodMetadata } from '@cabloy/zod-openapi';
|
|
4
|
+
import { Pipe, createArgumentPipe, setArgumentPipe } from 'vona-module-a-aspect';
|
|
2
5
|
import * as ModuleInfo from '@cabloy/module-info';
|
|
3
6
|
import { Bean, Service, Scope } from 'vona-module-a-bean';
|
|
4
7
|
import { SymbolUseOnionOptions } from 'vona-module-a-onion';
|
|
5
|
-
import { SymbolRouteHandlersArgumentsValue, SymbolRouteHandlersArgumentsMeta, mergeFieldsOpenapiMetadata } from 'vona-module-a-openapi';
|
|
6
|
-
import { valid } from 'vona-module-a-validation';
|
|
8
|
+
import { SymbolRouteHandlersArgumentsValue, SymbolRouteHandlersArgumentsMeta, makeSchemaLikes, $schema, mergeFieldsOpenapiMetadata } from 'vona-module-a-openapi';
|
|
7
9
|
import { SymbolUploadValue } from 'vona-module-a-upload';
|
|
8
10
|
import http from 'node:http';
|
|
9
11
|
import { Startup } from 'vona-module-a-startup';
|
|
10
12
|
import Router from 'find-my-way';
|
|
11
13
|
import { SymbolRouterMiddleware } from 'vona-module-a-executor';
|
|
14
|
+
import { z } from 'zod';
|
|
12
15
|
import { SymbolOpenApiOptions } from 'vona-module-a-openapiutils';
|
|
13
|
-
|
|
16
|
+
|
|
17
|
+
var _dec$5, _dec2$5, _class$5;
|
|
18
|
+
const __FieldsSystem = ['columns', 'where', 'orders', 'pageNo', 'pageSize'];
|
|
19
|
+
let PipeQuery = (_dec$5 = Pipe({
|
|
20
|
+
// ValidatorOptions
|
|
21
|
+
disableErrorMessages: false,
|
|
22
|
+
errorHttpStatusCode: HttpStatus.BAD_REQUEST,
|
|
23
|
+
loose: false,
|
|
24
|
+
strict: false
|
|
25
|
+
}), _dec2$5 = BeanInfo({
|
|
26
|
+
module: "a-web"
|
|
27
|
+
}), _dec$5(_class$5 = _dec2$5(_class$5 = class PipeQuery extends BeanBase {
|
|
28
|
+
async transform(value, metadata, options) {
|
|
29
|
+
if (!options.schema) throw new Error(`should specify the schema of pipeQuery: ${metadata.controller.name}.${metadata.method}#${metadata.index}`);
|
|
30
|
+
// validateSchema
|
|
31
|
+
value = await this.bean.validator.validateSchema(options.schema, value, options, metadata.field);
|
|
32
|
+
// transform
|
|
33
|
+
value = this._transform(value, options);
|
|
34
|
+
// ok
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
_transform(value, options) {
|
|
38
|
+
// 1. system: columns/where/orders/pageNo/pageSize
|
|
39
|
+
const params = this._transformSystem(value);
|
|
40
|
+
// 2. fields
|
|
41
|
+
this._transformFields(params, value, options);
|
|
42
|
+
// 3. system: orders
|
|
43
|
+
this._transformOrders(params, options);
|
|
44
|
+
// ok
|
|
45
|
+
return params;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// system: columns/where/orders/pageNo/pageSize
|
|
49
|
+
_transformSystem(value) {
|
|
50
|
+
const params = {};
|
|
51
|
+
// columns
|
|
52
|
+
if (!isNil(value.columns)) params.columns = value.columns;
|
|
53
|
+
// where
|
|
54
|
+
params.where = value.where ?? {};
|
|
55
|
+
// orders
|
|
56
|
+
if (!isNil(value.orders)) {
|
|
57
|
+
if (typeof value.orders === 'string') {
|
|
58
|
+
if (value.orders.startsWith('[') && value.orders.endsWith(']')) {
|
|
59
|
+
params.orders = JSON.parse(value.orders);
|
|
60
|
+
} else {
|
|
61
|
+
params.orders = [value.orders.split(',')];
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
params.orders = value.orders;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// pageNo/pageSize
|
|
68
|
+
if (!isNil(value.pageNo) && !isNil(value.pageSize)) {
|
|
69
|
+
params.offset = (value.pageNo - 1) * value.pageSize;
|
|
70
|
+
params.limit = value.pageSize;
|
|
71
|
+
}
|
|
72
|
+
// ok
|
|
73
|
+
return params;
|
|
74
|
+
}
|
|
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;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
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);
|
|
140
|
+
}
|
|
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_';
|
|
152
|
+
}
|
|
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);
|
|
182
|
+
} else {
|
|
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);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}) || _class$5) || _class$5);
|
|
194
|
+
const ArgQueryPro$1 = createArgumentPipe('a-web:query');
|
|
195
|
+
|
|
196
|
+
var _dec$4, _dec2$4, _class$4;
|
|
197
|
+
let PipeValid = (_dec$4 = Pipe({
|
|
198
|
+
// ValidatorOptions
|
|
199
|
+
disableErrorMessages: false,
|
|
200
|
+
errorHttpStatusCode: HttpStatus.BAD_REQUEST,
|
|
201
|
+
loose: false,
|
|
202
|
+
strict: false
|
|
203
|
+
}), _dec2$4 = BeanInfo({
|
|
204
|
+
module: "a-web"
|
|
205
|
+
}), _dec$4(_class$4 = _dec2$4(_class$4 = class PipeValid extends BeanBase {
|
|
206
|
+
async transform(value, metadata, options) {
|
|
207
|
+
if (options.schema) {
|
|
208
|
+
// validateSchema
|
|
209
|
+
return await this.bean.validator.validateSchema(options.schema, value, options, metadata.field);
|
|
210
|
+
}
|
|
211
|
+
return value;
|
|
212
|
+
}
|
|
213
|
+
}) || _class$4) || _class$4);
|
|
214
|
+
const ArgValid = createArgumentPipe('a-web:valid');
|
|
14
215
|
|
|
15
216
|
async function middlewareGuard(ctx, next) {
|
|
16
217
|
// check handler
|
|
@@ -35,6 +236,7 @@ function extractValue(ctx, argMeta) {
|
|
|
35
236
|
return exchangeKeyForValue(ctx, argMeta.type, argMeta.field);
|
|
36
237
|
}
|
|
37
238
|
function exchangeKeyForValue(ctx, type, field) {
|
|
239
|
+
if (!type) throw new Error('argument type should not empty');
|
|
38
240
|
const req = ctx.request;
|
|
39
241
|
const res = ctx.response;
|
|
40
242
|
const modes = {
|
|
@@ -79,8 +281,6 @@ async function middlewarePipe(ctx, next) {
|
|
|
79
281
|
// check handler
|
|
80
282
|
const handler = ctx.getHandler();
|
|
81
283
|
if (!handler) return next();
|
|
82
|
-
// body parser
|
|
83
|
-
await ctx.app.bean._getBean('a-body.service.body').parse(true);
|
|
84
284
|
// arguments
|
|
85
285
|
ctx[SymbolRouteHandlersArgumentsValue] = await _transformArguments(ctx, ctx.getController(), handler);
|
|
86
286
|
// next
|
|
@@ -99,7 +299,7 @@ async function _transformArguments(ctx, controller, handler) {
|
|
|
99
299
|
length: paramtypes.length
|
|
100
300
|
});
|
|
101
301
|
for (let index = args.length - 1; index >= 0; index--) {
|
|
102
|
-
const argMeta = argsMeta.find(item => item
|
|
302
|
+
const argMeta = argsMeta.find(item => item?.index === index);
|
|
103
303
|
if (!argMeta) continue;
|
|
104
304
|
// extractValue
|
|
105
305
|
const value = await _extractArgumentValue(ctx, argMeta);
|
|
@@ -120,6 +320,7 @@ async function _transformArguments(ctx, controller, handler) {
|
|
|
120
320
|
async function _transformArgument(ctx, argMeta, metadata, value) {
|
|
121
321
|
// pipes
|
|
122
322
|
const pipes = composePipes(ctx, argMeta, (beanInstance, value, options, _next) => {
|
|
323
|
+
if (!isNil(options.argIndex) && argMeta.index !== options.argIndex) return value;
|
|
123
324
|
return beanInstance.transform(value, metadata, options);
|
|
124
325
|
});
|
|
125
326
|
if (pipes.length === 0) return value;
|
|
@@ -171,11 +372,6 @@ function composePipes(ctx, argMeta, executeCustom) {
|
|
|
171
372
|
function _collectArgumentMiddlewares(onionPipe, argMeta) {
|
|
172
373
|
if (!argMeta.pipes) return;
|
|
173
374
|
return argMeta.pipes.map(pipe => {
|
|
174
|
-
if (typeof pipe !== 'function') {
|
|
175
|
-
pipe = valid({
|
|
176
|
-
schema: pipe
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
375
|
const {
|
|
180
376
|
pipeName,
|
|
181
377
|
options
|
|
@@ -309,24 +505,23 @@ let BeanRouter = (_dec$3 = Bean(), _dec2$3 = BeanInfo({
|
|
|
309
505
|
}
|
|
310
506
|
}) || _class$3) || _class$3);
|
|
311
507
|
function classControllerMiddleware(ctx) {
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
const controller = ctx.app.bean._getBean(beanFullName);
|
|
508
|
+
const handlerName = ctx.getHandlerName();
|
|
509
|
+
const controller = ctx.getControllerBean();
|
|
315
510
|
return controller[handlerName](...(ctx[SymbolRouteHandlersArgumentsValue] || []));
|
|
316
511
|
}
|
|
317
512
|
async function routeStartMiddleware(ctx, next) {
|
|
318
513
|
// next
|
|
319
514
|
const res = await next();
|
|
320
|
-
// invoke
|
|
321
|
-
await ctx.
|
|
515
|
+
// invoke callbacks: handle secondly
|
|
516
|
+
await ctx.commitsDone();
|
|
322
517
|
// ok
|
|
323
518
|
return res;
|
|
324
519
|
}
|
|
325
520
|
async function routeTailDoneMiddleware(ctx, next) {
|
|
326
521
|
// next
|
|
327
522
|
const res = await next();
|
|
328
|
-
// invoke
|
|
329
|
-
await ctx.
|
|
523
|
+
// invoke callbacks: handle firstly
|
|
524
|
+
await ctx.commitsDone();
|
|
330
525
|
// ok
|
|
331
526
|
return res;
|
|
332
527
|
}
|
|
@@ -343,7 +538,7 @@ async function routeTailDoneMiddleware(ctx, next) {
|
|
|
343
538
|
// // next
|
|
344
539
|
// const res = await next();
|
|
345
540
|
// // invoke callbackes: handle secondly
|
|
346
|
-
// await ctx.
|
|
541
|
+
// await ctx.commitsDone();
|
|
347
542
|
// // ok
|
|
348
543
|
// return res;
|
|
349
544
|
// };
|
|
@@ -362,7 +557,7 @@ async function routeTailDoneMiddleware(ctx, next) {
|
|
|
362
557
|
// // next
|
|
363
558
|
// const res = await next();
|
|
364
559
|
// // invoke callbackes: handle firstly
|
|
365
|
-
// await ctx.
|
|
560
|
+
// await ctx.commitsDone();
|
|
366
561
|
// // ok
|
|
367
562
|
// return res;
|
|
368
563
|
// };
|
|
@@ -514,6 +709,86 @@ let ScopeModuleAWeb = (_dec = Scope(), _dec2 = BeanInfo({
|
|
|
514
709
|
|
|
515
710
|
/** scope: end */
|
|
516
711
|
|
|
712
|
+
function createPipesArgumentDecorator(paramType, extractValue) {
|
|
713
|
+
return function (field, ...schemaLikes) {
|
|
714
|
+
return function (target, prop, index) {
|
|
715
|
+
const hasParamField = typeof field === 'string';
|
|
716
|
+
const paramField = hasParamField ? field : undefined;
|
|
717
|
+
const paramSchemaLikes = hasParamField ? schemaLikes : [field, ...schemaLikes].filter(item => !!item);
|
|
718
|
+
const paramtypes = appMetadata.getMetadata('design:paramtypes', target, prop);
|
|
719
|
+
let metaType;
|
|
720
|
+
if (paramType === 'file') {
|
|
721
|
+
metaType = z.string().openapi({
|
|
722
|
+
format: 'binary'
|
|
723
|
+
});
|
|
724
|
+
} else if (paramType === 'files') {
|
|
725
|
+
metaType = z.array(z.string().openapi({
|
|
726
|
+
format: 'binary'
|
|
727
|
+
}));
|
|
728
|
+
} else {
|
|
729
|
+
metaType = paramtypes[index];
|
|
730
|
+
}
|
|
731
|
+
const argSchema = makeSchemaLikes(paramSchemaLikes, metaType);
|
|
732
|
+
setArgumentPipe('a-web:valid', {
|
|
733
|
+
type: paramType,
|
|
734
|
+
field: paramField,
|
|
735
|
+
schema: argSchema,
|
|
736
|
+
extractValue
|
|
737
|
+
}, target, prop, index);
|
|
738
|
+
};
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
function Param(property, ...schemaLikes) {
|
|
743
|
+
return createPipesArgumentDecorator('param')(property, ...schemaLikes);
|
|
744
|
+
}
|
|
745
|
+
function Query(property, ...schemaLikes) {
|
|
746
|
+
return createPipesArgumentDecorator('query')(property, ...schemaLikes);
|
|
747
|
+
}
|
|
748
|
+
function Body(property, ...schemaLikes) {
|
|
749
|
+
return createPipesArgumentDecorator('body')(property, ...schemaLikes);
|
|
750
|
+
}
|
|
751
|
+
function Headers(property, ...schemaLikes) {
|
|
752
|
+
return createPipesArgumentDecorator('headers')(property, ...schemaLikes);
|
|
753
|
+
}
|
|
754
|
+
function Fields(property, ...schemaLikes) {
|
|
755
|
+
return createPipesArgumentDecorator('fields')(property, ...schemaLikes);
|
|
756
|
+
}
|
|
757
|
+
function Field(property, ...schemaLikes) {
|
|
758
|
+
return createPipesArgumentDecorator('field')(property, ...schemaLikes);
|
|
759
|
+
}
|
|
760
|
+
function Files(property, ...schemaLikes) {
|
|
761
|
+
return createPipesArgumentDecorator('files')(property, ...schemaLikes);
|
|
762
|
+
}
|
|
763
|
+
function File(property, ...schemaLikes) {
|
|
764
|
+
return createPipesArgumentDecorator('file')(property, ...schemaLikes);
|
|
765
|
+
}
|
|
766
|
+
function User(...schemaLikes) {
|
|
767
|
+
return createPipesArgumentDecorator('user')(undefined, ...schemaLikes);
|
|
768
|
+
}
|
|
769
|
+
function ArgQueryPro(schemaLike, transformFn) {
|
|
770
|
+
return function (target, prop, index) {
|
|
771
|
+
const schema = $schema(schemaLike);
|
|
772
|
+
setArgumentPipe('a-web:query', {
|
|
773
|
+
type: 'query',
|
|
774
|
+
schema,
|
|
775
|
+
transformFn
|
|
776
|
+
}, target, prop, index);
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
const Arg = {
|
|
780
|
+
param: Param,
|
|
781
|
+
query: Query,
|
|
782
|
+
body: Body,
|
|
783
|
+
headers: Headers,
|
|
784
|
+
fields: Fields,
|
|
785
|
+
field: Field,
|
|
786
|
+
files: Files,
|
|
787
|
+
file: File,
|
|
788
|
+
user: User,
|
|
789
|
+
queryPro: ArgQueryPro
|
|
790
|
+
};
|
|
791
|
+
|
|
517
792
|
function Controller(path, options) {
|
|
518
793
|
if (typeof path === 'string') {
|
|
519
794
|
options = Object.assign({}, options, {
|
|
@@ -611,4 +886,4 @@ function $apiPathAndCombineParamsAndQuery(path, options) {
|
|
|
611
886
|
return combineParamsAndQuery(path, options);
|
|
612
887
|
}
|
|
613
888
|
|
|
614
|
-
export { $apiPath, $apiPathAndCombineParamsAndQuery, BeanRouter, Controller, Dto, Main, RequestMapping, ScopeModuleAWeb, ServiceWeb, StartupListen, SymbolRequestMappingHandler, Web, config, 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 };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Constructable } from 'vona';
|
|
2
|
+
import type { SchemaLike } from 'vona-module-a-openapiutils';
|
|
3
|
+
import type z from 'zod';
|
|
4
|
+
import type { TypePipeOptionsQueryTransform } from '../../bean/pipe.query.ts';
|
|
5
|
+
declare function Param(): ParameterDecorator;
|
|
6
|
+
declare function Param(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
7
|
+
declare function Param(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
8
|
+
declare function Query(): ParameterDecorator;
|
|
9
|
+
declare function Query(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
10
|
+
declare function Query(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
11
|
+
declare function Body(): ParameterDecorator;
|
|
12
|
+
declare function Body(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
13
|
+
declare function Body(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
14
|
+
declare function Headers(): ParameterDecorator;
|
|
15
|
+
declare function Headers(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
16
|
+
declare function Headers(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
17
|
+
declare function Fields(): ParameterDecorator;
|
|
18
|
+
declare function Fields(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
19
|
+
declare function Fields(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
20
|
+
declare function Field(): ParameterDecorator;
|
|
21
|
+
declare function Field(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
22
|
+
declare function Field(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
23
|
+
declare function Files(): ParameterDecorator;
|
|
24
|
+
declare function Files(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
25
|
+
declare function Files(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
26
|
+
declare function File(): ParameterDecorator;
|
|
27
|
+
declare function File(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
28
|
+
declare function File(property: string, ...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
29
|
+
declare function User(...schemaLikes: SchemaLike[]): ParameterDecorator;
|
|
30
|
+
declare function ArgQueryPro(schemaLike: z.ZodType | Constructable, transformFn?: TypePipeOptionsQueryTransform | string): any;
|
|
31
|
+
export declare const Arg: {
|
|
32
|
+
param: typeof Param;
|
|
33
|
+
query: typeof Query;
|
|
34
|
+
body: typeof Body;
|
|
35
|
+
headers: typeof Headers;
|
|
36
|
+
fields: typeof Fields;
|
|
37
|
+
field: typeof Field;
|
|
38
|
+
files: typeof Files;
|
|
39
|
+
file: typeof File;
|
|
40
|
+
user: typeof User;
|
|
41
|
+
queryPro: typeof ArgQueryPro;
|
|
42
|
+
};
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RouteHandlerArgumentType, TypeExtractValue } from 'vona-module-a-openapi';
|
|
2
|
+
import type { SchemaLike } from 'vona-module-a-openapiutils';
|
|
3
|
+
export declare function createPipesArgumentDecorator(paramType: RouteHandlerArgumentType, extractValue?: TypeExtractValue): (field?: string | SchemaLike, ...schemaLikes: SchemaLike[]) => ParameterDecorator;
|
|
@@ -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<
|
|
31
|
+
controller: ServiceOnion<IControllerRecord>;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
declare module 'vona' {
|
package/dist/types/dto.d.ts
CHANGED
|
@@ -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<
|
|
16
|
+
dto: ServiceOnion<IDtoRecord>;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
declare module 'vona' {
|