@fluojs/validation 1.0.5 → 2.0.0

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.
Files changed (43) hide show
  1. package/README.ko.md +47 -1
  2. package/README.md +48 -1
  3. package/dist/decorators.d.ts +71 -69
  4. package/dist/decorators.d.ts.map +1 -1
  5. package/dist/decorators.js +73 -133
  6. package/dist/internal/decorator-factories.d.ts +12 -0
  7. package/dist/internal/decorator-factories.d.ts.map +1 -0
  8. package/dist/internal/decorator-factories.js +32 -0
  9. package/dist/internal/decorator-metadata.d.ts +7 -0
  10. package/dist/internal/decorator-metadata.d.ts.map +1 -0
  11. package/dist/internal/decorator-metadata.js +38 -0
  12. package/dist/internal/dto-materialization.d.ts +45 -0
  13. package/dist/internal/dto-materialization.d.ts.map +1 -0
  14. package/dist/internal/dto-materialization.js +204 -0
  15. package/dist/internal/dto-metadata-cache.d.ts +17 -0
  16. package/dist/internal/dto-metadata-cache.d.ts.map +1 -0
  17. package/dist/internal/dto-metadata-cache.js +49 -0
  18. package/dist/internal/enum-values.d.ts +2 -0
  19. package/dist/internal/enum-values.d.ts.map +1 -0
  20. package/dist/internal/enum-values.js +16 -0
  21. package/dist/internal/object-utils.d.ts +30 -0
  22. package/dist/internal/object-utils.d.ts.map +1 -0
  23. package/dist/internal/object-utils.js +53 -0
  24. package/dist/internal/rule-handlers.d.ts +19 -0
  25. package/dist/internal/rule-handlers.d.ts.map +1 -0
  26. package/dist/internal/rule-handlers.js +209 -0
  27. package/dist/internal/validation-issues.d.ts +13 -0
  28. package/dist/internal/validation-issues.d.ts.map +1 -0
  29. package/dist/internal/validation-issues.js +44 -0
  30. package/dist/internal/validator-js-adapter.d.ts +5 -0
  31. package/dist/internal/validator-js-adapter.d.ts.map +1 -0
  32. package/dist/internal/validator-js-adapter.js +88 -0
  33. package/dist/mapped-types.d.ts +1 -1
  34. package/dist/mapped-types.d.ts.map +1 -1
  35. package/dist/mapped-types.js +1 -1
  36. package/dist/standard-schema.d.ts +1 -1
  37. package/dist/standard-schema.d.ts.map +1 -1
  38. package/dist/types.d.ts +18 -3
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/validation.d.ts +2 -2
  41. package/dist/validation.d.ts.map +1 -1
  42. package/dist/validation.js +24 -509
  43. package/package.json +4 -4
@@ -0,0 +1,209 @@
1
+ import { isPlainObject } from './object-utils.js';
2
+ import { runValidatorJs } from './validator-js-adapter.js';
3
+ function isEmptyValue(value) {
4
+ return value === '' || value === null || value === undefined;
5
+ }
6
+ const ruleHandlers = {
7
+ validateIf: {
8
+ defaultCode: 'VALIDATE_IF',
9
+ describe: field => `${field} is conditionally invalid.`,
10
+ validate: () => true
11
+ },
12
+ defined: {
13
+ defaultCode: 'REQUIRED',
14
+ describe: field => `${field} is required.`,
15
+ validate: (_rule, value) => value !== undefined && value !== null
16
+ },
17
+ optional: {
18
+ defaultCode: 'OPTIONAL',
19
+ describe: field => `${field} is optional.`,
20
+ validate: () => true
21
+ },
22
+ equals: {
23
+ defaultCode: 'EQUALS',
24
+ describe: (field, rule) => `${field} must equal ${String(rule.value)}.`,
25
+ validate: (rule, value) => value === rule.value
26
+ },
27
+ notEquals: {
28
+ defaultCode: 'NOT_EQUALS',
29
+ describe: (field, rule) => `${field} must not equal ${String(rule.value)}.`,
30
+ validate: (rule, value) => value !== rule.value
31
+ },
32
+ empty: {
33
+ defaultCode: 'EMPTY',
34
+ describe: field => `${field} must be empty.`,
35
+ validate: (_rule, value) => isEmptyValue(value)
36
+ },
37
+ notEmpty: {
38
+ defaultCode: 'NOT_EMPTY',
39
+ describe: field => `${field} should not be empty.`,
40
+ validate: (_rule, value) => !isEmptyValue(value)
41
+ },
42
+ in: {
43
+ defaultCode: 'IN',
44
+ describe: field => `${field} must be one of the allowed values.`,
45
+ validate: (rule, value) => rule.values.includes(value)
46
+ },
47
+ notIn: {
48
+ defaultCode: 'NOT_IN',
49
+ describe: field => `${field} contains a forbidden value.`,
50
+ validate: (rule, value) => !rule.values.includes(value)
51
+ },
52
+ string: {
53
+ defaultCode: 'INVALID_STRING',
54
+ describe: field => `${field} must be a string.`,
55
+ validate: (_rule, value) => typeof value === 'string'
56
+ },
57
+ number: {
58
+ defaultCode: 'INVALID_NUMBER',
59
+ describe: field => `${field} must be a number.`,
60
+ validate: (rule, value) => typeof value === 'number' && (rule.allowNaN || !Number.isNaN(value))
61
+ },
62
+ boolean: {
63
+ defaultCode: 'INVALID_BOOLEAN',
64
+ describe: field => `${field} must be a boolean.`,
65
+ validate: (_rule, value) => typeof value === 'boolean'
66
+ },
67
+ date: {
68
+ defaultCode: 'INVALID_DATE',
69
+ describe: field => `${field} must be a Date instance.`,
70
+ validate: (_rule, value) => value instanceof Date && !Number.isNaN(value.getTime())
71
+ },
72
+ array: {
73
+ defaultCode: 'INVALID_ARRAY',
74
+ describe: field => `${field} must be an array.`,
75
+ validate: (_rule, value) => Array.isArray(value)
76
+ },
77
+ object: {
78
+ defaultCode: 'INVALID_OBJECT',
79
+ describe: field => `${field} must be an object.`,
80
+ validate: (_rule, value) => isPlainObject(value)
81
+ },
82
+ enum: {
83
+ defaultCode: 'INVALID_ENUM',
84
+ describe: field => `${field} must be a supported enum value.`,
85
+ validate: (rule, value) => rule.values.includes(value)
86
+ },
87
+ int: {
88
+ defaultCode: 'INVALID_INT',
89
+ describe: field => `${field} must be an integer.`,
90
+ validate: (_rule, value) => typeof value === 'number' && Number.isInteger(value)
91
+ },
92
+ divisibleBy: {
93
+ defaultCode: 'DIVISIBLE_BY',
94
+ describe: (field, rule) => `${field} must be divisible by ${String(rule.value)}.`,
95
+ validate: (rule, value) => typeof value === 'number' && !Number.isNaN(value) && value % rule.value === 0
96
+ },
97
+ positive: {
98
+ defaultCode: 'POSITIVE',
99
+ describe: field => `${field} must be positive.`,
100
+ validate: (_rule, value) => typeof value === 'number' && value > 0
101
+ },
102
+ negative: {
103
+ defaultCode: 'NEGATIVE',
104
+ describe: field => `${field} must be negative.`,
105
+ validate: (_rule, value) => typeof value === 'number' && value < 0
106
+ },
107
+ min: {
108
+ defaultCode: 'MIN',
109
+ describe: (field, rule) => `${field} must be greater than or equal to ${String(rule.value)}.`,
110
+ validate: (rule, value) => typeof value === 'number' && !Number.isNaN(value) && value >= rule.value
111
+ },
112
+ max: {
113
+ defaultCode: 'MAX',
114
+ describe: (field, rule) => `${field} must be less than or equal to ${String(rule.value)}.`,
115
+ validate: (rule, value) => typeof value === 'number' && !Number.isNaN(value) && value <= rule.value
116
+ },
117
+ minDate: {
118
+ defaultCode: 'MIN_DATE',
119
+ describe: (field, rule) => `${field} must be on or after ${rule.value.toISOString()}.`,
120
+ validate: (rule, value) => value instanceof Date && !Number.isNaN(value.getTime()) && value.getTime() >= rule.value.getTime()
121
+ },
122
+ maxDate: {
123
+ defaultCode: 'MAX_DATE',
124
+ describe: (field, rule) => `${field} must be on or before ${rule.value.toISOString()}.`,
125
+ validate: (rule, value) => value instanceof Date && !Number.isNaN(value.getTime()) && value.getTime() <= rule.value.getTime()
126
+ },
127
+ contains: {
128
+ defaultCode: 'CONTAINS',
129
+ describe: (field, rule) => `${field} must contain ${rule.value}.`,
130
+ validate: (rule, value) => typeof value === 'string' && value.includes(rule.value)
131
+ },
132
+ notContains: {
133
+ defaultCode: 'NOT_CONTAINS',
134
+ describe: (field, rule) => `${field} must not contain ${rule.value}.`,
135
+ validate: (rule, value) => typeof value === 'string' && !value.includes(rule.value)
136
+ },
137
+ length: {
138
+ defaultCode: 'LENGTH',
139
+ describe: field => `${field} must have a valid length.`,
140
+ validate: (rule, value) => typeof value === 'string' && value.length >= rule.min && (rule.max === undefined || value.length <= rule.max)
141
+ },
142
+ minLength: {
143
+ defaultCode: 'MIN_LENGTH',
144
+ describe: (field, rule) => `${field} must have length at least ${String(rule.value)}.`,
145
+ validate: (rule, value) => typeof value === 'string' && value.length >= rule.value
146
+ },
147
+ maxLength: {
148
+ defaultCode: 'MAX_LENGTH',
149
+ describe: (field, rule) => `${field} must have length at most ${String(rule.value)}.`,
150
+ validate: (rule, value) => typeof value === 'string' && value.length <= rule.value
151
+ },
152
+ nested: {
153
+ defaultCode: 'INVALID_NESTED',
154
+ describe: field => `${field} contains invalid nested data.`,
155
+ validate: () => true
156
+ },
157
+ validatorjs: {
158
+ defaultCode: 'INVALID_FIELD',
159
+ describe: field => `${field} is invalid.`,
160
+ validate: (rule, value) => runValidatorJs(rule, value)
161
+ },
162
+ arrayContains: {
163
+ defaultCode: 'ARRAY_CONTAINS',
164
+ describe: field => `${field} must contain the required values.`,
165
+ validate: (rule, value) => Array.isArray(value) && rule.values.every(expected => value.includes(expected))
166
+ },
167
+ arrayNotContains: {
168
+ defaultCode: 'ARRAY_NOT_CONTAINS',
169
+ describe: field => `${field} contains forbidden values.`,
170
+ validate: (rule, value) => Array.isArray(value) && rule.values.every(expected => !value.includes(expected))
171
+ },
172
+ arrayNotEmpty: {
173
+ defaultCode: 'ARRAY_NOT_EMPTY',
174
+ describe: field => `${field} must not be an empty array.`,
175
+ validate: (_rule, value) => Array.isArray(value) && value.length > 0
176
+ },
177
+ arrayMinSize: {
178
+ defaultCode: 'ARRAY_MIN_SIZE',
179
+ describe: (field, rule) => `${field} must contain at least ${String(rule.value)} items.`,
180
+ validate: (rule, value) => Array.isArray(value) && value.length >= rule.value
181
+ },
182
+ arrayMaxSize: {
183
+ defaultCode: 'ARRAY_MAX_SIZE',
184
+ describe: (field, rule) => `${field} must contain at most ${String(rule.value)} items.`,
185
+ validate: (rule, value) => Array.isArray(value) && value.length <= rule.value
186
+ },
187
+ arrayUnique: {
188
+ defaultCode: 'ARRAY_UNIQUE',
189
+ describe: field => `${field} must contain unique values.`,
190
+ validate: (rule, value) => {
191
+ if (!Array.isArray(value)) return false;
192
+ const seen = new Set();
193
+ for (const entry of value) {
194
+ const key = rule.selector ? rule.selector(entry) : entry;
195
+ if (seen.has(key)) return false;
196
+ seen.add(key);
197
+ }
198
+ return true;
199
+ }
200
+ },
201
+ custom: {
202
+ defaultCode: 'INVALID_FIELD',
203
+ describe: field => `${field} is invalid.`,
204
+ validate: () => true
205
+ }
206
+ };
207
+ export function getRuleHandler(rule) {
208
+ return ruleHandlers[rule.kind];
209
+ }
@@ -0,0 +1,13 @@
1
+ import type { ValidationRuleResult } from '@fluojs/core/request-pipeline';
2
+ import type { ValidationIssue } from '../types.js';
3
+ export declare function normalizeResult(result: ValidationRuleResult, field: string | undefined, source: ValidationIssue['source'], fallback: {
4
+ readonly code: string;
5
+ readonly message: string;
6
+ }): ValidationIssue[];
7
+ export declare function joinFieldPath(parent: string, child?: string): string;
8
+ export declare function prefixIssues(issues: readonly ValidationIssue[], fieldPrefix: string, source: ValidationIssue['source']): ValidationIssue[];
9
+ export declare function buildIssue(fallback: {
10
+ readonly code: string;
11
+ readonly message: string;
12
+ }, field: string, source: ValidationIssue['source']): ValidationIssue;
13
+ //# sourceMappingURL=validation-issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-issues.d.ts","sourceRoot":"","sources":["../../src/internal/validation-issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA2B,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAEnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAenD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,QAAQ,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5D,eAAe,EAAE,CAcnB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAChC,eAAe,EAAE,CAEnB;AAED,wBAAgB,UAAU,CACxB,QAAQ,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7D,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,GAChC,eAAe,CAOjB"}
@@ -0,0 +1,44 @@
1
+ function normalizeIssue(issue, field, source) {
2
+ return {
3
+ code: issue.code,
4
+ field: issue.field ?? field,
5
+ message: issue.message,
6
+ source: issue.source ?? source
7
+ };
8
+ }
9
+ export function normalizeResult(result, field, source, fallback) {
10
+ if (result === undefined || result === true) {
11
+ return [];
12
+ }
13
+ if (result === false) {
14
+ return [{
15
+ code: fallback.code,
16
+ field,
17
+ message: fallback.message,
18
+ source
19
+ }];
20
+ }
21
+ if (Array.isArray(result)) {
22
+ return result.map(issue => normalizeIssue(issue, field, source));
23
+ }
24
+ return [normalizeIssue(result, field, source)];
25
+ }
26
+ export function joinFieldPath(parent, child) {
27
+ if (!child) return parent;
28
+ return child.startsWith('[') ? `${parent}${child}` : `${parent}.${child}`;
29
+ }
30
+ export function prefixIssues(issues, fieldPrefix, source) {
31
+ return issues.map(issue => ({
32
+ ...issue,
33
+ field: joinFieldPath(fieldPrefix, issue.field),
34
+ source: issue.source ?? source
35
+ }));
36
+ }
37
+ export function buildIssue(fallback, field, source) {
38
+ return {
39
+ code: fallback.code,
40
+ field,
41
+ message: fallback.message,
42
+ source
43
+ };
44
+ }
@@ -0,0 +1,5 @@
1
+ import type { DtoFieldValidationRule } from '@fluojs/core/request-pipeline';
2
+ export declare function runValidatorJs(rule: Extract<DtoFieldValidationRule, {
3
+ kind: 'validatorjs';
4
+ }>, value: unknown): boolean;
5
+ //# sourceMappingURL=validator-js-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator-js-adapter.d.ts","sourceRoot":"","sources":["../../src/internal/validator-js-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAE5E,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,sBAAsB,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAoDtH"}
@@ -0,0 +1,88 @@
1
+ import validator from 'validator';
2
+ export function runValidatorJs(rule, value) {
3
+ if (rule.validator === 'latitude') {
4
+ return typeof value === 'number' && Number.isFinite(value) && value >= -90 && value <= 90;
5
+ }
6
+ if (rule.validator === 'longitude') {
7
+ return typeof value === 'number' && Number.isFinite(value) && value >= -180 && value <= 180;
8
+ }
9
+ if (typeof value !== 'string') {
10
+ return false;
11
+ }
12
+ switch (rule.validator) {
13
+ case 'alpha':
14
+ return validator.isAlpha(value);
15
+ case 'alphanumeric':
16
+ return validator.isAlphanumeric(value);
17
+ case 'ascii':
18
+ return validator.isAscii(value);
19
+ case 'base64':
20
+ return validator.isBase64(value);
21
+ case 'booleanString':
22
+ return validator.isBoolean(value);
23
+ case 'currency':
24
+ return validator.isCurrency(value, rule.args?.[0]);
25
+ case 'dataURI':
26
+ return validator.isDataURI(value);
27
+ case 'dateString':
28
+ return validator.isISO8601(value);
29
+ case 'decimal':
30
+ return validator.isDecimal(value);
31
+ case 'email':
32
+ return validator.isEmail(value, rule.args?.[0]);
33
+ case 'fqdn':
34
+ return validator.isFQDN(value, rule.args?.[0]);
35
+ case 'hexColor':
36
+ return validator.isHexColor(value);
37
+ case 'hexadecimal':
38
+ return validator.isHexadecimal(value);
39
+ case 'ip':
40
+ return validator.isIP(value, rule.args?.[0]);
41
+ case 'isbn':
42
+ return validator.isISBN(value, rule.args?.[0]);
43
+ case 'issn':
44
+ return validator.isISSN(value);
45
+ case 'json':
46
+ return validator.isJSON(value);
47
+ case 'jwt':
48
+ return validator.isJWT(value);
49
+ case 'locale':
50
+ return validator.isLocale(value);
51
+ case 'lowercase':
52
+ return validator.isLowercase(value);
53
+ case 'magnetURI':
54
+ return validator.isMagnetURI(value);
55
+ case 'matches':
56
+ return validator.matches(value, rule.args?.[0], rule.args?.[1]);
57
+ case 'mimeType':
58
+ return validator.isMimeType(value);
59
+ case 'mobilePhone':
60
+ return validator.isMobilePhone(value, rule.args?.[0]);
61
+ case 'mongoId':
62
+ return validator.isMongoId(value);
63
+ case 'numberString':
64
+ return validator.isNumeric(value);
65
+ case 'port':
66
+ return validator.isPort(value);
67
+ case 'postalCode':
68
+ return validator.isPostalCode(value, rule.args?.[0] ?? 'any');
69
+ case 'rgbColor':
70
+ return validator.isRgbColor(value, rule.args?.[0]);
71
+ case 'rfc3339':
72
+ return validator.isRFC3339(value);
73
+ case 'semVer':
74
+ return validator.isSemVer(value);
75
+ case 'uppercase':
76
+ return validator.isUppercase(value);
77
+ case 'url':
78
+ return validator.isURL(value, rule.args?.[0]);
79
+ case 'uuid':
80
+ return validator.isUUID(value, rule.args?.[0]);
81
+ case 'iso8601':
82
+ return validator.isISO8601(value);
83
+ case 'latLong':
84
+ return validator.isLatLong(value);
85
+ default:
86
+ return false;
87
+ }
88
+ }
@@ -1,4 +1,4 @@
1
- import { type Constructor } from '@fluojs/core';
1
+ import type { Constructor } from '@fluojs/core';
2
2
  type DtoConstructor<T = object> = Constructor<T>;
3
3
  /**
4
4
  * Derive a DTO class that keeps only the selected properties from a base DTO.
@@ -1 +1 @@
1
- {"version":3,"file":"mapped-types.d.ts","sourceRoot":"","sources":["../src/mapped-types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEjB,MAAM,cAAc,CAAC;AAUtB,KAAK,cAAc,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;AAoEjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,cAAc,EAAE,IAAI,SAAS,OAAO,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAC5G,OAAO,EAAE,KAAK,EACd,IAAI,EAAE,SAAS,IAAI,EAAE,GACpB,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAcjD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,cAAc,EAAE,IAAI,SAAS,OAAO,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAC5G,OAAO,EAAE,KAAK,EACd,IAAI,EAAE,SAAS,IAAI,EAAE,GACpB,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAcjD;AAED,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAC5B,CAAC,SAAS,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAC/C,SAAS,CAAC,KAAK,EAAE,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC;AAE3D,KAAK,oBAAoB,CAAC,SAAS,SAAS,SAAS,cAAc,EAAE,IAAI,mBAAmB,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE9H;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,SAAS,SAAS,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,EAC/G,GAAG,QAAQ,EAAE,SAAS,GACrB,cAAc,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAkBjD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,SAAS,cAAc,EAAE,OAAO,EAAE,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CA6BtH"}
1
+ {"version":3,"file":"mapped-types.d.ts","sourceRoot":"","sources":["../src/mapped-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,cAAc,CAAC;AAUrE,KAAK,cAAc,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;AAoEjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,cAAc,EAAE,IAAI,SAAS,OAAO,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAC5G,OAAO,EAAE,KAAK,EACd,IAAI,EAAE,SAAS,IAAI,EAAE,GACpB,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAcjD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,cAAc,EAAE,IAAI,SAAS,OAAO,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAC5G,OAAO,EAAE,KAAK,EACd,IAAI,EAAE,SAAS,IAAI,EAAE,GACpB,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAcjD;AAED,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAC5B,CAAC,SAAS,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAC/C,SAAS,CAAC,KAAK,EAAE,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,GAAG,KAAK,CAAC;AAE3D,KAAK,oBAAoB,CAAC,SAAS,SAAS,SAAS,cAAc,EAAE,IAAI,mBAAmB,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE9H;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,SAAS,SAAS,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,EAC/G,GAAG,QAAQ,EAAE,SAAS,GACrB,cAAc,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAkBjD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,SAAS,cAAc,EAAE,OAAO,EAAE,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CA6BtH"}
@@ -1,4 +1,4 @@
1
- import { appendClassValidationRule, appendDtoFieldValidationRule, defineDtoFieldBindingMetadata, getClassValidationRules, getDtoBindingSchema, getDtoValidationSchema } from '@fluojs/core/internal';
1
+ import { appendClassValidationRule, appendDtoFieldValidationRule, defineDtoFieldBindingMetadata, getClassValidationRules, getDtoBindingSchema, getDtoValidationSchema } from '@fluojs/core/request-pipeline';
2
2
  function setClassName(target, name) {
3
3
  Object.defineProperty(target, 'name', {
4
4
  configurable: true,
@@ -1,5 +1,5 @@
1
1
  import type { StandardSchemaV1 } from '@standard-schema/spec';
2
- import type { CustomClassValidator } from '@fluojs/core/internal';
2
+ import type { CustomClassValidator } from '@fluojs/core/request-pipeline';
3
3
  /**
4
4
  * Standard Schema v1-compatible validator accepted by `ValidateClass`.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAIlE;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AA0CpG;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAkBlF;AA4CD;;;;;GAKG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAgBzG"}
1
+ {"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAI1E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AA0CpG;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAkBlF;AA4CD;;;;;GAKG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,CAgBzG"}
package/dist/types.d.ts CHANGED
@@ -12,13 +12,28 @@ export interface ValidationIssue {
12
12
  /** Optional metadata source that produced this rule. */
13
13
  source?: MetadataSource;
14
14
  }
15
+ /** Controls DTO materialization behavior. */
16
+ export interface MaterializeOptions {
17
+ /** Policy for safe own enumerable input properties not declared by the DTO. */
18
+ readonly undeclaredProperties?: 'preserve' | 'reject';
19
+ }
15
20
  /**
16
21
  * Validation engine contract used by HTTP binding and app-level validation flows.
17
22
  */
18
23
  export interface Validator {
19
- /** Validates an existing instance without materializing nested objects. */
24
+ /**
25
+ * Validates an existing root DTO or plain object.
26
+ * Plain nested values may be temporarily materialized for nested DTO rules
27
+ * without replacing the caller's properties.
28
+ */
20
29
  validate(value: unknown, target: Constructor): MaybePromise<void>;
21
- /** Materializes and validates a value into a typed DTO instance. */
22
- materialize<T>(value: unknown, target: Constructor<T>): MaybePromise<T>;
30
+ /**
31
+ * Materializes and validates a value into a typed DTO instance.
32
+ *
33
+ * @param value Root value to materialize.
34
+ * @param target Requested DTO constructor.
35
+ * @param options Optional materialization policy.
36
+ */
37
+ materialize<T>(value: unknown, target: Constructor<T>, options?: MaterializeOptions): MaybePromise<T>;
23
38
  }
24
39
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClE,oEAAoE;IACpE,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;CACzE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,6CAA6C;AAC7C,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClE;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;CACvG"}
@@ -1,10 +1,10 @@
1
1
  import type { Constructor } from '@fluojs/core';
2
- import type { Validator } from './types.js';
2
+ import type { MaterializeOptions, Validator } from './types.js';
3
3
  /**
4
4
  * Represents the default validator.
5
5
  */
6
6
  export declare class DefaultValidator implements Validator {
7
7
  validate(value: unknown, target: Constructor): Promise<void>;
8
- materialize<T>(value: unknown, target: Constructor<T>): Promise<T>;
8
+ materialize<T>(value: unknown, target: Constructor<T>, options?: MaterializeOptions): Promise<T>;
9
9
  }
10
10
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,cAAc,CAAC;AAatB,OAAO,KAAK,EAAmB,SAAS,EAAE,MAAM,YAAY,CAAC;AAsyB7D;;GAEG;AACH,qBAAa,gBAAiB,YAAW,SAAS;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5D,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAYzE"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEZ,MAAM,cAAc,CAAC;AAetB,OAAO,KAAK,EAAE,kBAAkB,EAAmB,SAAS,EAAE,MAAM,YAAY,CAAC;AA+OjF;;GAEG;AACH,qBAAa,gBAAiB,YAAW,SAAS;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5D,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,CAAC,CAAC;CAqB3G"}