@hestjs/validation 0.1.2

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.
@@ -0,0 +1,179 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import 'reflect-metadata';
3
+ /**
4
+ * 验证元数据键
5
+ */
6
+ export const VALIDATION_METADATA_KEY = Symbol('validation');
7
+ /**
8
+ * 创建属性验证装饰器
9
+ */
10
+ function createPropertyValidator(schema, options = {}) {
11
+ return function (target, propertyKey) {
12
+ const existingMetadata = Reflect.getMetadata(VALIDATION_METADATA_KEY, target.constructor) || { properties: [] };
13
+ const propertyMetadata = {
14
+ propertyKey,
15
+ schema,
16
+ isOptional: options.optional,
17
+ message: options.message,
18
+ };
19
+ existingMetadata.properties.push(propertyMetadata);
20
+ Reflect.defineMetadata(VALIDATION_METADATA_KEY, existingMetadata, target.constructor);
21
+ };
22
+ }
23
+ /**
24
+ * 字符串验证装饰器
25
+ */
26
+ export function IsString(options = {}) {
27
+ let schema = Type.String();
28
+ if (options.minLength !== undefined) {
29
+ schema = Type.String({ minLength: options.minLength });
30
+ }
31
+ if (options.maxLength !== undefined) {
32
+ schema = Type.String({ maxLength: options.maxLength });
33
+ }
34
+ if (options.pattern) {
35
+ schema = Type.String({ pattern: options.pattern });
36
+ }
37
+ if (options.minLength !== undefined && options.maxLength !== undefined) {
38
+ schema = Type.String({ minLength: options.minLength, maxLength: options.maxLength });
39
+ }
40
+ return createPropertyValidator(schema, { message: options.message });
41
+ }
42
+ /**
43
+ * 数字验证装饰器
44
+ */
45
+ export function IsNumber(options = {}) {
46
+ let schema = Type.Number();
47
+ if (options.minimum !== undefined) {
48
+ schema = Type.Number({ minimum: options.minimum });
49
+ }
50
+ if (options.maximum !== undefined) {
51
+ schema = Type.Number({ maximum: options.maximum });
52
+ }
53
+ if (options.multipleOf !== undefined) {
54
+ schema = Type.Number({ multipleOf: options.multipleOf });
55
+ }
56
+ if (options.minimum !== undefined && options.maximum !== undefined) {
57
+ schema = Type.Number({ minimum: options.minimum, maximum: options.maximum });
58
+ }
59
+ return createPropertyValidator(schema, { message: options.message });
60
+ }
61
+ /**
62
+ * 整数验证装饰器
63
+ */
64
+ export function IsInteger(options = {}) {
65
+ let schema = Type.Integer();
66
+ if (options.minimum !== undefined && options.maximum !== undefined) {
67
+ schema = Type.Integer({ minimum: options.minimum, maximum: options.maximum });
68
+ }
69
+ else if (options.minimum !== undefined) {
70
+ schema = Type.Integer({ minimum: options.minimum });
71
+ }
72
+ else if (options.maximum !== undefined) {
73
+ schema = Type.Integer({ maximum: options.maximum });
74
+ }
75
+ return createPropertyValidator(schema, { message: options.message });
76
+ }
77
+ /**
78
+ * 布尔值验证装饰器
79
+ */
80
+ export function IsBoolean(options = {}) {
81
+ const schema = Type.Boolean();
82
+ return createPropertyValidator(schema, { message: options.message });
83
+ }
84
+ /**
85
+ * 邮箱验证装饰器
86
+ */
87
+ export function IsEmail(options = {}) {
88
+ const schema = Type.String({
89
+ pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'
90
+ });
91
+ return createPropertyValidator(schema, { message: options.message || 'Must be a valid email address' });
92
+ }
93
+ /**
94
+ * URL 验证装饰器
95
+ */
96
+ export function IsUrl(options = {}) {
97
+ const schema = Type.String({
98
+ pattern: '^https?:\\/\\/.+'
99
+ });
100
+ return createPropertyValidator(schema, { message: options.message || 'Must be a valid URL' });
101
+ }
102
+ /**
103
+ * 数组验证装饰器
104
+ */
105
+ export function IsArray(itemSchema, options = {}) {
106
+ let schema = itemSchema ? Type.Array(itemSchema) : Type.Array(Type.Any());
107
+ if (options.minItems !== undefined || options.maxItems !== undefined) {
108
+ const arrayOptions = {};
109
+ if (options.minItems !== undefined)
110
+ arrayOptions.minItems = options.minItems;
111
+ if (options.maxItems !== undefined)
112
+ arrayOptions.maxItems = options.maxItems;
113
+ schema = itemSchema ? Type.Array(itemSchema, arrayOptions) : Type.Array(Type.Any(), arrayOptions);
114
+ }
115
+ return createPropertyValidator(schema, { message: options.message });
116
+ }
117
+ /**
118
+ * 枚举验证装饰器
119
+ */
120
+ export function IsEnum(enumValues, options = {}) {
121
+ const schema = Type.Union(enumValues.map(value => Type.Literal(value)));
122
+ return createPropertyValidator(schema, { message: options.message || `Must be one of: ${enumValues.join(', ')}` });
123
+ }
124
+ /**
125
+ * 日期验证装饰器
126
+ */
127
+ export function IsDate(options = {}) {
128
+ const schema = Type.String({ format: 'date-time' });
129
+ return createPropertyValidator(schema, { message: options.message || 'Must be a valid date' });
130
+ }
131
+ /**
132
+ * 可选字段装饰器
133
+ */
134
+ export function IsOptional() {
135
+ return function (target, propertyKey) {
136
+ const existingMetadata = Reflect.getMetadata(VALIDATION_METADATA_KEY, target.constructor) || { properties: [] };
137
+ // 查找对应的属性元数据并标记为可选
138
+ const propertyMetadata = existingMetadata.properties.find(p => p.propertyKey === propertyKey);
139
+ if (propertyMetadata) {
140
+ propertyMetadata.isOptional = true;
141
+ }
142
+ Reflect.defineMetadata(VALIDATION_METADATA_KEY, existingMetadata, target.constructor);
143
+ };
144
+ }
145
+ /**
146
+ * 长度验证装饰器
147
+ */
148
+ export function Length(min, max, options = {}) {
149
+ const schema = max !== undefined
150
+ ? Type.String({ minLength: min, maxLength: max })
151
+ : Type.String({ minLength: min });
152
+ const message = options.message || (max !== undefined
153
+ ? `Length must be between ${min} and ${max} characters`
154
+ : `Length must be at least ${min} characters`);
155
+ return createPropertyValidator(schema, { message });
156
+ }
157
+ /**
158
+ * 最小值验证装饰器
159
+ */
160
+ export function Min(value, options = {}) {
161
+ const schema = Type.Number({ minimum: value });
162
+ return createPropertyValidator(schema, { message: options.message || `Must be at least ${value}` });
163
+ }
164
+ /**
165
+ * 最大值验证装饰器
166
+ */
167
+ export function Max(value, options = {}) {
168
+ const schema = Type.Number({ maximum: value });
169
+ return createPropertyValidator(schema, { message: options.message || `Must be at most ${value}` });
170
+ }
171
+ /**
172
+ * 模式匹配验证装饰器
173
+ */
174
+ export function Matches(pattern, options = {}) {
175
+ const patternString = pattern instanceof RegExp ? pattern.source : pattern;
176
+ const schema = Type.String({ pattern: patternString });
177
+ return createPropertyValidator(schema, { message: options.message || `Must match pattern: ${patternString}` });
178
+ }
179
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/decorators/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 用户创建 DTO 示例
3
+ */
4
+ export declare class CreateUserDto {
5
+ name: string;
6
+ email: string;
7
+ age: number;
8
+ password: string;
9
+ bio?: string;
10
+ tags?: string[];
11
+ }
12
+ /**
13
+ * 用户更新 DTO 示例
14
+ */
15
+ export declare class UpdateUserDto {
16
+ name?: string;
17
+ email?: string;
18
+ age?: number;
19
+ bio?: string;
20
+ tags?: string[];
21
+ }
22
+ /**
23
+ * 查询参数 DTO 示例
24
+ */
25
+ export declare class UserQueryDto {
26
+ search?: string;
27
+ page?: number;
28
+ limit?: number;
29
+ sortBy?: string;
30
+ sortOrder?: 'asc' | 'desc';
31
+ }
32
+ //# sourceMappingURL=examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../../src/dto/examples.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,qBAAa,aAAa;IAExB,IAAI,EAAG,MAAM,CAAC;IAGd,KAAK,EAAG,MAAM,CAAC;IAKf,GAAG,EAAG,MAAM,CAAC;IAIb,QAAQ,EAAG,MAAM,CAAC;IAIlB,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,aAAa;IAGxB,IAAI,CAAC,EAAE,MAAM,CAAC;IAId,KAAK,CAAC,EAAE,MAAM,CAAC;IAMf,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,YAAY;IAGvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,IAAI,CAAC,EAAE,MAAM,CAAC;IAMd,KAAK,CAAC,EAAE,MAAM,CAAC;IAIf,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B"}
@@ -0,0 +1,127 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Type } from '@sinclair/typebox';
11
+ import { IsString, IsEmail, IsNumber, IsOptional, IsArray, Min, Max, Length } from '../decorators/validation';
12
+ /**
13
+ * 用户创建 DTO 示例
14
+ */
15
+ export class CreateUserDto {
16
+ name;
17
+ email;
18
+ age;
19
+ password;
20
+ bio;
21
+ tags;
22
+ }
23
+ __decorate([
24
+ IsString({ minLength: 2, maxLength: 50 }),
25
+ __metadata("design:type", String)
26
+ ], CreateUserDto.prototype, "name", void 0);
27
+ __decorate([
28
+ IsEmail(),
29
+ __metadata("design:type", String)
30
+ ], CreateUserDto.prototype, "email", void 0);
31
+ __decorate([
32
+ IsNumber(),
33
+ Min(0),
34
+ Max(120),
35
+ __metadata("design:type", Number)
36
+ ], CreateUserDto.prototype, "age", void 0);
37
+ __decorate([
38
+ IsString(),
39
+ Length(8, 100),
40
+ __metadata("design:type", String)
41
+ ], CreateUserDto.prototype, "password", void 0);
42
+ __decorate([
43
+ IsOptional(),
44
+ IsString(),
45
+ __metadata("design:type", String)
46
+ ], CreateUserDto.prototype, "bio", void 0);
47
+ __decorate([
48
+ IsOptional(),
49
+ IsArray(Type.String()),
50
+ __metadata("design:type", Array)
51
+ ], CreateUserDto.prototype, "tags", void 0);
52
+ /**
53
+ * 用户更新 DTO 示例
54
+ */
55
+ export class UpdateUserDto {
56
+ name;
57
+ email;
58
+ age;
59
+ bio;
60
+ tags;
61
+ }
62
+ __decorate([
63
+ IsOptional(),
64
+ IsString({ minLength: 2, maxLength: 50 }),
65
+ __metadata("design:type", String)
66
+ ], UpdateUserDto.prototype, "name", void 0);
67
+ __decorate([
68
+ IsOptional(),
69
+ IsEmail(),
70
+ __metadata("design:type", String)
71
+ ], UpdateUserDto.prototype, "email", void 0);
72
+ __decorate([
73
+ IsOptional(),
74
+ IsNumber(),
75
+ Min(0),
76
+ Max(120),
77
+ __metadata("design:type", Number)
78
+ ], UpdateUserDto.prototype, "age", void 0);
79
+ __decorate([
80
+ IsOptional(),
81
+ IsString(),
82
+ __metadata("design:type", String)
83
+ ], UpdateUserDto.prototype, "bio", void 0);
84
+ __decorate([
85
+ IsOptional(),
86
+ IsArray(Type.String()),
87
+ __metadata("design:type", Array)
88
+ ], UpdateUserDto.prototype, "tags", void 0);
89
+ /**
90
+ * 查询参数 DTO 示例
91
+ */
92
+ export class UserQueryDto {
93
+ search;
94
+ page;
95
+ limit;
96
+ sortBy;
97
+ sortOrder;
98
+ }
99
+ __decorate([
100
+ IsOptional(),
101
+ IsString(),
102
+ __metadata("design:type", String)
103
+ ], UserQueryDto.prototype, "search", void 0);
104
+ __decorate([
105
+ IsOptional(),
106
+ IsNumber(),
107
+ Min(1),
108
+ __metadata("design:type", Number)
109
+ ], UserQueryDto.prototype, "page", void 0);
110
+ __decorate([
111
+ IsOptional(),
112
+ IsNumber(),
113
+ Min(1),
114
+ Max(100),
115
+ __metadata("design:type", Number)
116
+ ], UserQueryDto.prototype, "limit", void 0);
117
+ __decorate([
118
+ IsOptional(),
119
+ IsString(),
120
+ __metadata("design:type", String)
121
+ ], UserQueryDto.prototype, "sortBy", void 0);
122
+ __decorate([
123
+ IsOptional(),
124
+ IsString(),
125
+ __metadata("design:type", String)
126
+ ], UserQueryDto.prototype, "sortOrder", void 0);
127
+ //# sourceMappingURL=examples.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.js","sourceRoot":"","sources":["../../src/dto/examples.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,OAAO,EACP,GAAG,EACH,GAAG,EACH,MAAM,EACP,MAAM,0BAA0B,CAAC;AAElC;;GAEG;AACH,MAAM,OAAO,aAAa;IAExB,IAAI,CAAU;IAGd,KAAK,CAAU;IAKf,GAAG,CAAU;IAIb,QAAQ,CAAU;IAIlB,GAAG,CAAU;IAIb,IAAI,CAAY;CACjB;AArBC;IADC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;;2CAC5B;AAGd;IADC,OAAO,EAAE;;4CACK;AAKf;IAHC,QAAQ,EAAE;IACV,GAAG,CAAC,CAAC,CAAC;IACN,GAAG,CAAC,GAAG,CAAC;;0CACI;AAIb;IAFC,QAAQ,EAAE;IACV,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC;;+CACG;AAIlB;IAFC,UAAU,EAAE;IACZ,QAAQ,EAAE;;0CACE;AAIb;IAFC,UAAU,EAAE;IACZ,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;;2CACP;AAGlB;;GAEG;AACH,MAAM,OAAO,aAAa;IAGxB,IAAI,CAAU;IAId,KAAK,CAAU;IAMf,GAAG,CAAU;IAIb,GAAG,CAAU;IAIb,IAAI,CAAY;CACjB;AAnBC;IAFC,UAAU,EAAE;IACZ,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;;2CAC5B;AAId;IAFC,UAAU,EAAE;IACZ,OAAO,EAAE;;4CACK;AAMf;IAJC,UAAU,EAAE;IACZ,QAAQ,EAAE;IACV,GAAG,CAAC,CAAC,CAAC;IACN,GAAG,CAAC,GAAG,CAAC;;0CACI;AAIb;IAFC,UAAU,EAAE;IACZ,QAAQ,EAAE;;0CACE;AAIb;IAFC,UAAU,EAAE;IACZ,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;;2CACP;AAGlB;;GAEG;AACH,MAAM,OAAO,YAAY;IAGvB,MAAM,CAAU;IAKhB,IAAI,CAAU;IAMd,KAAK,CAAU;IAIf,MAAM,CAAU;IAIhB,SAAS,CAAkB;CAC5B;AApBC;IAFC,UAAU,EAAE;IACZ,QAAQ,EAAE;;4CACK;AAKhB;IAHC,UAAU,EAAE;IACZ,QAAQ,EAAE;IACV,GAAG,CAAC,CAAC,CAAC;;0CACO;AAMd;IAJC,UAAU,EAAE;IACZ,QAAQ,EAAE;IACV,GAAG,CAAC,CAAC,CAAC;IACN,GAAG,CAAC,GAAG,CAAC;;2CACM;AAIf;IAFC,UAAU,EAAE;IACZ,QAAQ,EAAE;;4CACK;AAIhB;IAFC,UAAU,EAAE;IACZ,QAAQ,EAAE;;+CACgB"}
@@ -0,0 +1,9 @@
1
+ export * from './decorators/validation';
2
+ export * from './decorators/custom';
3
+ export * from './pipes/validation.pipe';
4
+ export * from './interceptors/validation.interceptor';
5
+ export * from './dto/examples';
6
+ export * from './utils/validation.utils';
7
+ export { Type, type TSchema, type Static } from '@sinclair/typebox';
8
+ export { Value } from '@sinclair/typebox/value';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,uCAAuC,CAAC;AAGtD,cAAc,gBAAgB,CAAC;AAG/B,cAAc,0BAA0B,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // 装饰器
2
+ export * from './decorators/validation';
3
+ export * from './decorators/custom';
4
+ // 管道
5
+ export * from './pipes/validation.pipe';
6
+ // 拦截器
7
+ export * from './interceptors/validation.interceptor';
8
+ // DTO 示例
9
+ export * from './dto/examples';
10
+ // 工具函数
11
+ export * from './utils/validation.utils';
12
+ // TypeBox 相关导出
13
+ export { Type } from '@sinclair/typebox';
14
+ export { Value } from '@sinclair/typebox/value';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM;AACN,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AAEpC,KAAK;AACL,cAAc,yBAAyB,CAAC;AAExC,MAAM;AACN,cAAc,uCAAuC,CAAC;AAEtD,SAAS;AACT,cAAc,gBAAgB,CAAC;AAE/B,OAAO;AACP,cAAc,0BAA0B,CAAC;AAEzC,eAAe;AACf,OAAO,EAAE,IAAI,EAA6B,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { CallHandler, ExecutionContext, Interceptor } from "@hestjs/core";
2
+ /**
3
+ * 参数验证元数据
4
+ */
5
+ export interface ParameterValidationMetadata {
6
+ index: number;
7
+ dtoClass: new () => any;
8
+ }
9
+ /**
10
+ * Body 验证装饰器
11
+ */
12
+ export declare function Body<T>(dtoClass: new () => T): (target: any, propertyKey: string | symbol | undefined, parameterIndex: number) => void;
13
+ /**
14
+ * Query 验证装饰器
15
+ */
16
+ export declare function Query<T>(dtoClass: new () => T): (target: any, propertyKey: string | symbol | undefined, parameterIndex: number) => void;
17
+ /**
18
+ * 验证拦截器
19
+ */
20
+ export declare class ValidationInterceptor implements Interceptor {
21
+ private readonly validationPipe;
22
+ constructor();
23
+ intercept(context: ExecutionContext, next: CallHandler): Promise<any>;
24
+ /**
25
+ * 获取请求体数据
26
+ */
27
+ private getRequestBody;
28
+ }
29
+ //# sourceMappingURL=validation.interceptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.interceptor.d.ts","sourceRoot":"","sources":["../../src/interceptors/validation.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,gBAAgB,EAEhB,WAAW,EACZ,MAAM,cAAc,CAAC;AAQtB;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,GAAG,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,IAEzC,QAAQ,GAAG,EACX,aAAa,MAAM,GAAG,MAAM,GAAG,SAAS,EACxC,gBAAgB,MAAM,UAwBzB;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,IAE1C,QAAQ,GAAG,EACX,aAAa,MAAM,GAAG,MAAM,GAAG,SAAS,EACxC,gBAAgB,MAAM,UAwBzB;AAED;;GAEG;AACH,qBACa,qBAAsB,YAAW,WAAW;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;;IAU1C,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IA6E3E;;OAEG;YACW,cAAc;CAkC7B"}
@@ -0,0 +1,164 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable, } from "@hestjs/core";
11
+ import { ValidationException, ValidationPipe } from "../pipes/validation.pipe";
12
+ /**
13
+ * 参数验证元数据键
14
+ */
15
+ const PARAMETER_VALIDATION_KEY = Symbol("parameter:validation");
16
+ /**
17
+ * Body 验证装饰器
18
+ */
19
+ export function Body(dtoClass) {
20
+ return function (target, propertyKey, parameterIndex) {
21
+ const existingMetadata = Reflect.getMetadata(PARAMETER_VALIDATION_KEY, target, propertyKey) || [];
22
+ existingMetadata.push({
23
+ index: parameterIndex,
24
+ dtoClass,
25
+ });
26
+ Reflect.defineMetadata(PARAMETER_VALIDATION_KEY, existingMetadata, target, propertyKey);
27
+ // console.log('🔍 Body装饰器: 已存储验证元数据', {
28
+ // target: target.constructor.name,
29
+ // method: String(propertyKey),
30
+ // parameterIndex,
31
+ // dtoClass: dtoClass.name
32
+ // });
33
+ };
34
+ }
35
+ /**
36
+ * Query 验证装饰器
37
+ */
38
+ export function Query(dtoClass) {
39
+ return function (target, propertyKey, parameterIndex) {
40
+ const existingMetadata = Reflect.getMetadata(PARAMETER_VALIDATION_KEY, target, propertyKey) || [];
41
+ existingMetadata.push({
42
+ index: parameterIndex,
43
+ dtoClass,
44
+ });
45
+ Reflect.defineMetadata(PARAMETER_VALIDATION_KEY, existingMetadata, target, propertyKey);
46
+ // console.log('🔍 Query装饰器: 已存储验证元数据', {
47
+ // target: target.constructor.name,
48
+ // method: String(propertyKey),
49
+ // parameterIndex,
50
+ // dtoClass: dtoClass.name
51
+ // });
52
+ };
53
+ }
54
+ /**
55
+ * 验证拦截器
56
+ */
57
+ let ValidationInterceptor = class ValidationInterceptor {
58
+ validationPipe;
59
+ constructor() {
60
+ this.validationPipe = new ValidationPipe({
61
+ whitelist: true,
62
+ forbidNonWhitelisted: false,
63
+ transform: true,
64
+ });
65
+ }
66
+ async intercept(context, next) {
67
+ const httpContext = context.switchToHttp();
68
+ const request = httpContext.getRequest();
69
+ const handler = context.getHandler();
70
+ const target = context.getClass();
71
+ // console.log('🔍 ValidationInterceptor: 开始验证', handler.name);
72
+ // console.log('🔍 ValidationInterceptor: context 类型:', typeof context);
73
+ // console.log('🔍 ValidationInterceptor: context 键:', Object.keys(context));
74
+ // 尝试获取原始的 Hono Context
75
+ const honoContext = context.context || request;
76
+ // console.log('🔍 ValidationInterceptor: honoContext 类型:', typeof honoContext);
77
+ // 获取参数验证元数据
78
+ const paramValidations = Reflect.getMetadata(PARAMETER_VALIDATION_KEY, target.prototype, handler.name) || [];
79
+ // console.log('🔍 ValidationInterceptor: 找到参数验证数量:', paramValidations.length);
80
+ // console.log('🔍 ValidationInterceptor: 检查目标:', target.name, '方法:', handler.name);
81
+ // console.log('🔍 ValidationInterceptor: 尝试读取元数据键:', PARAMETER_VALIDATION_KEY.toString());
82
+ if (paramValidations.length === 0) {
83
+ // console.log('🔍 ValidationInterceptor: 没有找到验证元数据,跳过验证');
84
+ return next.handle();
85
+ }
86
+ try {
87
+ // 验证请求体和查询参数
88
+ for (const validation of paramValidations) {
89
+ const { dtoClass } = validation;
90
+ // console.log('🔍 ValidationInterceptor: 验证 DTO 类:', dtoClass.name);
91
+ // 获取请求数据 - 优先使用 Hono Context
92
+ const body = await this.getRequestBody(honoContext);
93
+ // console.log('🔍 ValidationInterceptor: 请求体数据:', body);
94
+ if (body && Object.keys(body).length > 0) {
95
+ // 进行验证
96
+ // console.log('🔍 ValidationInterceptor: 开始验证数据');
97
+ const validatedData = await this.validationPipe.validate(dtoClass, body);
98
+ // console.log('🔍 ValidationInterceptor: 验证通过,数据:', validatedData);
99
+ // 将验证后的数据存储到请求中
100
+ honoContext.validatedBody = validatedData;
101
+ }
102
+ else {
103
+ // console.log('🔍 ValidationInterceptor: 请求体为空,跳过验证');
104
+ }
105
+ }
106
+ return next.handle();
107
+ }
108
+ catch (error) {
109
+ // console.log("🔍 ValidationInterceptor: 验证失败:", error);
110
+ if (error instanceof ValidationException) {
111
+ // 抛出 HTTP 异常
112
+ const validationError = new Error("Validation failed");
113
+ validationError.status = 400;
114
+ validationError.details = {
115
+ message: "Validation failed",
116
+ errors: error.getMessages(),
117
+ statusCode: 400,
118
+ };
119
+ throw validationError;
120
+ }
121
+ throw error;
122
+ }
123
+ }
124
+ /**
125
+ * 获取请求体数据
126
+ */
127
+ async getRequestBody(request) {
128
+ try {
129
+ // console.log('🔍 getRequestBody: 检查请求对象类型:', typeof request);
130
+ // console.log('🔍 getRequestBody: 请求对象键:', Object.keys(request || {}));
131
+ // 检查是否是 Hono Context
132
+ if (request && request.req) {
133
+ // console.log('🔍 getRequestBody: 检测到 Hono Context,使用 req.json()');
134
+ const body = await request.req.json();
135
+ // console.log('🔍 getRequestBody: 从 Hono Context 获取到的数据:', body);
136
+ return body;
137
+ }
138
+ // 直接尝试调用 json 方法
139
+ if (request && typeof request.json === "function") {
140
+ // console.log('🔍 getRequestBody: 使用 request.json()');
141
+ const body = await request.json();
142
+ // console.log('🔍 getRequestBody: 从 request.json() 获取到的数据:', body);
143
+ return body;
144
+ }
145
+ // 如果已经解析过了,直接返回
146
+ if (request && request.body) {
147
+ // console.log('🔍 getRequestBody: 使用已解析的 body:', request.body);
148
+ return request.body;
149
+ }
150
+ // console.log('🔍 getRequestBody: 无法获取请求体,返回空对象');
151
+ return {};
152
+ }
153
+ catch (error) {
154
+ // console.log('🔍 getRequestBody: 获取请求体时出错:', error);
155
+ return {};
156
+ }
157
+ }
158
+ };
159
+ ValidationInterceptor = __decorate([
160
+ Injectable(),
161
+ __metadata("design:paramtypes", [])
162
+ ], ValidationInterceptor);
163
+ export { ValidationInterceptor };
164
+ //# sourceMappingURL=validation.interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.interceptor.js","sourceRoot":"","sources":["../../src/interceptors/validation.interceptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type TSchema } from "@sinclair/typebox";
2
+ /**
3
+ * 验证错误
4
+ */
5
+ export declare class ValidationError extends Error {
6
+ field: string;
7
+ value: any;
8
+ constraint: string;
9
+ constructor(message: string, field: string, value: any, constraint: string);
10
+ }
11
+ /**
12
+ * 验证异常 - 包含多个验证错误
13
+ */
14
+ export declare class ValidationException extends Error {
15
+ errors: ValidationError[];
16
+ constructor(errors: ValidationError[]);
17
+ getMessages(): string[];
18
+ getFormattedMessage(): string;
19
+ }
20
+ /**
21
+ * 验证管道选项
22
+ */
23
+ export interface ValidationPipeOptions {
24
+ whitelist?: boolean;
25
+ forbidNonWhitelisted?: boolean;
26
+ transform?: boolean;
27
+ disableErrorMessages?: boolean;
28
+ validateCustomDecorators?: boolean;
29
+ }
30
+ /**
31
+ * 验证管道
32
+ */
33
+ export declare class ValidationPipe {
34
+ private readonly options;
35
+ constructor(options?: ValidationPipeOptions);
36
+ /**
37
+ * 验证对象
38
+ */
39
+ validate<T>(target: new () => T, object: any): Promise<T>;
40
+ /**
41
+ * 过滤属性(白名单模式)
42
+ */
43
+ private filterProperties;
44
+ /**
45
+ * 获取自定义错误消息
46
+ */
47
+ private getCustomMessage;
48
+ /**
49
+ * 验证单个值
50
+ */
51
+ validateValue<T>(schema: TSchema, value: any, fieldName?: string): T;
52
+ /**
53
+ * 创建 DTO 验证装饰器
54
+ */
55
+ static createDtoValidator<T>(dtoClass: new () => T): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
56
+ }
57
+ //# sourceMappingURL=validation.pipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.pipe.d.ts","sourceRoot":"","sources":["../../src/pipes/validation.pipe.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAOvD;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IAG/B,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,GAAG;IACV,UAAU,EAAE,MAAM;gBAHzB,OAAO,EAAE,MAAM,EACR,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,GAAG,EACV,UAAU,EAAE,MAAM;CAK5B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IACzB,MAAM,EAAE,eAAe,EAAE;gBAAzB,MAAM,EAAE,eAAe,EAAE;IAK5C,WAAW,IAAI,MAAM,EAAE;IAIvB,mBAAmB,IAAI,MAAM;CAK9B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED;;GAEG;AACH,qBACa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,GAAE,qBAA0B;IAW/C;;OAEG;IACG,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IA8E/D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,GAAG,EACV,SAAS,GAAE,MAAgB,GAC1B,CAAC;IA4BJ;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,IAE9C,QAAQ,GAAG,EACX,aAAa,MAAM,GAAG,MAAM,EAC5B,gBAAgB,MAAM;CAU3B"}