@fluojs/validation 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.ko.md +138 -0
- package/README.md +118 -0
- package/dist/decorators.d.ts +165 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +443 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/mapped-types.d.ts +99 -0
- package/dist/mapped-types.d.ts.map +1 -0
- package/dist/mapped-types.js +207 -0
- package/dist/standard-schema.d.ts +6 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +75 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/validation.d.ts +7 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +653 -0
- package/package.json +61 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { metadataSymbol } from '@fluojs/core/internal';
|
|
2
|
+
import { createClassValidatorFromStandardSchema, isStandardSchemaLike } from './standard-schema.js';
|
|
3
|
+
const standardDtoValidationMetadataKey = Symbol.for('fluo.standard.dto-validation');
|
|
4
|
+
const standardClassValidationMetadataKey = Symbol.for('fluo.standard.class-validation');
|
|
5
|
+
function getStandardMetadataBag(metadata) {
|
|
6
|
+
if (metadata === null || metadata === undefined) {
|
|
7
|
+
throw new Error('Decorator metadata is not available. Ensure your environment supports TC39 decorator metadata (Stage 3).');
|
|
8
|
+
}
|
|
9
|
+
void metadataSymbol;
|
|
10
|
+
return metadata;
|
|
11
|
+
}
|
|
12
|
+
function getStandardDtoValidationMap(metadata) {
|
|
13
|
+
const bag = getStandardMetadataBag(metadata);
|
|
14
|
+
const current = bag[standardDtoValidationMetadataKey];
|
|
15
|
+
if (current) {
|
|
16
|
+
return current;
|
|
17
|
+
}
|
|
18
|
+
const created = new Map();
|
|
19
|
+
bag[standardDtoValidationMetadataKey] = created;
|
|
20
|
+
return created;
|
|
21
|
+
}
|
|
22
|
+
function getStandardClassValidationList(metadata) {
|
|
23
|
+
const bag = getStandardMetadataBag(metadata);
|
|
24
|
+
const current = bag[standardClassValidationMetadataKey];
|
|
25
|
+
if (current) {
|
|
26
|
+
return current;
|
|
27
|
+
}
|
|
28
|
+
const created = [];
|
|
29
|
+
bag[standardClassValidationMetadataKey] = created;
|
|
30
|
+
return created;
|
|
31
|
+
}
|
|
32
|
+
function appendStandardDtoValidationRule(metadata, propertyKey, rule) {
|
|
33
|
+
const map = getStandardDtoValidationMap(metadata);
|
|
34
|
+
map.set(propertyKey, [...(map.get(propertyKey) ?? []), rule]);
|
|
35
|
+
}
|
|
36
|
+
function appendStandardClassValidationRule(metadata, rule) {
|
|
37
|
+
getStandardClassValidationList(metadata).push(rule);
|
|
38
|
+
}
|
|
39
|
+
function resolveClassValidator(validate) {
|
|
40
|
+
if (!isStandardSchemaLike(validate)) {
|
|
41
|
+
return validate;
|
|
42
|
+
}
|
|
43
|
+
return createClassValidatorFromStandardSchema(validate);
|
|
44
|
+
}
|
|
45
|
+
function createValidationDecorator(ruleFactory) {
|
|
46
|
+
const decorator = (_value, context) => {
|
|
47
|
+
appendStandardDtoValidationRule(context.metadata, context.name, ruleFactory());
|
|
48
|
+
};
|
|
49
|
+
return decorator;
|
|
50
|
+
}
|
|
51
|
+
function createValidationOptionsWithConfigDecorator(ruleFactory) {
|
|
52
|
+
return (value, options) => {
|
|
53
|
+
return createValidationDecorator(() => ruleFactory(value, options));
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function createFlagValidationDecorator(ruleFactory) {
|
|
57
|
+
return options => {
|
|
58
|
+
return createValidationDecorator(() => ruleFactory(options));
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createArrayValidationDecorator(ruleFactory) {
|
|
62
|
+
return (values, options) => {
|
|
63
|
+
return createValidationDecorator(() => ruleFactory(values, options));
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function createValidatorJsDecorator(validator) {
|
|
67
|
+
return (args, options) => {
|
|
68
|
+
return createValidationDecorator(() => ({
|
|
69
|
+
args,
|
|
70
|
+
kind: 'validatorjs',
|
|
71
|
+
validator,
|
|
72
|
+
...options
|
|
73
|
+
}));
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validates that the decorated field is a string value.
|
|
79
|
+
*
|
|
80
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
81
|
+
* @returns A field decorator that registers a string validation rule.
|
|
82
|
+
*/
|
|
83
|
+
export function IsString(options) {
|
|
84
|
+
return createValidationDecorator(() => ({
|
|
85
|
+
kind: 'string',
|
|
86
|
+
...options
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Validates that the decorated field is a number value.
|
|
92
|
+
*
|
|
93
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
94
|
+
* @returns A field decorator that registers a number validation rule.
|
|
95
|
+
*/
|
|
96
|
+
export function IsNumber(options) {
|
|
97
|
+
return createValidationDecorator(() => ({
|
|
98
|
+
kind: 'number',
|
|
99
|
+
...options
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validates that the decorated field is a boolean value.
|
|
105
|
+
*
|
|
106
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
107
|
+
* @returns A field decorator that registers a boolean validation rule.
|
|
108
|
+
*/
|
|
109
|
+
export function IsBoolean(options) {
|
|
110
|
+
return createValidationDecorator(() => ({
|
|
111
|
+
kind: 'boolean',
|
|
112
|
+
...options
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Applies subsequent validators only when the condition returns `true`.
|
|
118
|
+
*
|
|
119
|
+
* @param validateIf Predicate that decides whether subsequent validators should run.
|
|
120
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
121
|
+
* @returns A field decorator that adds conditional validation execution.
|
|
122
|
+
*/
|
|
123
|
+
export const ValidateIf = (validateIf, options) => createValidationDecorator(() => ({
|
|
124
|
+
kind: 'validateIf',
|
|
125
|
+
validateIf,
|
|
126
|
+
...options
|
|
127
|
+
}));
|
|
128
|
+
export const IsDefined = createFlagValidationDecorator(options => ({
|
|
129
|
+
kind: 'defined',
|
|
130
|
+
...options
|
|
131
|
+
}));
|
|
132
|
+
export const IsOptional = createFlagValidationDecorator(options => ({
|
|
133
|
+
kind: 'optional',
|
|
134
|
+
...options
|
|
135
|
+
}));
|
|
136
|
+
export const Equals = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
137
|
+
kind: 'equals',
|
|
138
|
+
value,
|
|
139
|
+
...options
|
|
140
|
+
}));
|
|
141
|
+
export const NotEquals = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
142
|
+
kind: 'notEquals',
|
|
143
|
+
value,
|
|
144
|
+
...options
|
|
145
|
+
}));
|
|
146
|
+
export const IsEmpty = createFlagValidationDecorator(options => ({
|
|
147
|
+
kind: 'empty',
|
|
148
|
+
...options
|
|
149
|
+
}));
|
|
150
|
+
export const IsNotEmpty = createFlagValidationDecorator(options => ({
|
|
151
|
+
kind: 'notEmpty',
|
|
152
|
+
...options
|
|
153
|
+
}));
|
|
154
|
+
export const IsIn = createArrayValidationDecorator((values, options) => ({
|
|
155
|
+
kind: 'in',
|
|
156
|
+
values,
|
|
157
|
+
...options
|
|
158
|
+
}));
|
|
159
|
+
export const IsNotIn = createArrayValidationDecorator((values, options) => ({
|
|
160
|
+
kind: 'notIn',
|
|
161
|
+
values,
|
|
162
|
+
...options
|
|
163
|
+
}));
|
|
164
|
+
export const IsDate = createFlagValidationDecorator(options => ({
|
|
165
|
+
kind: 'date',
|
|
166
|
+
...options
|
|
167
|
+
}));
|
|
168
|
+
export const IsArray = createFlagValidationDecorator(options => ({
|
|
169
|
+
kind: 'array',
|
|
170
|
+
...options
|
|
171
|
+
}));
|
|
172
|
+
export const IsObject = createFlagValidationDecorator(options => ({
|
|
173
|
+
kind: 'object',
|
|
174
|
+
...options
|
|
175
|
+
}));
|
|
176
|
+
export const IsInt = createFlagValidationDecorator(options => ({
|
|
177
|
+
kind: 'int',
|
|
178
|
+
...options
|
|
179
|
+
}));
|
|
180
|
+
export const IsPositive = createFlagValidationDecorator(options => ({
|
|
181
|
+
kind: 'positive',
|
|
182
|
+
...options
|
|
183
|
+
}));
|
|
184
|
+
export const IsNegative = createFlagValidationDecorator(options => ({
|
|
185
|
+
kind: 'negative',
|
|
186
|
+
...options
|
|
187
|
+
}));
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Validates that the field value is included in the given enum-like set.
|
|
191
|
+
*
|
|
192
|
+
* @param values Enum object or literal value list that defines the accepted set.
|
|
193
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
194
|
+
* @returns A field decorator that registers an enum-membership rule.
|
|
195
|
+
*/
|
|
196
|
+
export function IsEnum(values, options) {
|
|
197
|
+
const normalized = Array.isArray(values) ? values : Object.values(values);
|
|
198
|
+
return createValidationDecorator(() => ({
|
|
199
|
+
kind: 'enum',
|
|
200
|
+
values: normalized,
|
|
201
|
+
...options
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
export const IsDivisibleBy = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
205
|
+
kind: 'divisibleBy',
|
|
206
|
+
value,
|
|
207
|
+
...options
|
|
208
|
+
}));
|
|
209
|
+
export const Min = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
210
|
+
kind: 'min',
|
|
211
|
+
value,
|
|
212
|
+
...options
|
|
213
|
+
}));
|
|
214
|
+
export const Max = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
215
|
+
kind: 'max',
|
|
216
|
+
value,
|
|
217
|
+
...options
|
|
218
|
+
}));
|
|
219
|
+
export const MinDate = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
220
|
+
kind: 'minDate',
|
|
221
|
+
value,
|
|
222
|
+
...options
|
|
223
|
+
}));
|
|
224
|
+
export const MaxDate = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
225
|
+
kind: 'maxDate',
|
|
226
|
+
value,
|
|
227
|
+
...options
|
|
228
|
+
}));
|
|
229
|
+
export const Contains = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
230
|
+
kind: 'contains',
|
|
231
|
+
value,
|
|
232
|
+
...options
|
|
233
|
+
}));
|
|
234
|
+
export const NotContains = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
235
|
+
kind: 'notContains',
|
|
236
|
+
value,
|
|
237
|
+
...options
|
|
238
|
+
}));
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Validates string length using optional min/max boundaries.
|
|
242
|
+
*
|
|
243
|
+
* @param min Minimum inclusive length.
|
|
244
|
+
* @param max Optional maximum inclusive length.
|
|
245
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
246
|
+
* @returns A field decorator that registers a bounded-length rule.
|
|
247
|
+
*/
|
|
248
|
+
export function Length(min, max, options) {
|
|
249
|
+
return createValidationDecorator(() => ({
|
|
250
|
+
kind: 'length',
|
|
251
|
+
max,
|
|
252
|
+
min,
|
|
253
|
+
...options
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Validates a nested DTO instance using the provided constructor.
|
|
259
|
+
*
|
|
260
|
+
* @param dto DTO constructor (or lazy constructor factory) used for nested validation/materialization.
|
|
261
|
+
* @param options Optional validation behavior (`message`, `groups`, `always`, `each`).
|
|
262
|
+
* @returns A field decorator that registers recursive nested DTO validation.
|
|
263
|
+
*/
|
|
264
|
+
export function ValidateNested(dto, options) {
|
|
265
|
+
return createValidationDecorator(() => ({
|
|
266
|
+
dto,
|
|
267
|
+
kind: 'nested',
|
|
268
|
+
...options
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
271
|
+
export const MinLength = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
272
|
+
kind: 'minLength',
|
|
273
|
+
value,
|
|
274
|
+
...options
|
|
275
|
+
}));
|
|
276
|
+
export const MaxLength = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
277
|
+
kind: 'maxLength',
|
|
278
|
+
value,
|
|
279
|
+
...options
|
|
280
|
+
}));
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Validates the field using a regular expression pattern.
|
|
284
|
+
*
|
|
285
|
+
* @param pattern Pattern source (`RegExp` or string) passed to validator.js `matches`.
|
|
286
|
+
* @param modifiersOrOptions Regex modifiers string (for string patterns) or validation options.
|
|
287
|
+
* @param options Validation options used when modifiers are provided separately.
|
|
288
|
+
* @returns A field decorator that registers a regex-matching rule.
|
|
289
|
+
*/
|
|
290
|
+
export function Matches(pattern, modifiersOrOptions, options) {
|
|
291
|
+
const resolvedOptions = typeof modifiersOrOptions === 'object' ? modifiersOrOptions : options;
|
|
292
|
+
if (pattern instanceof RegExp) {
|
|
293
|
+
return createValidationDecorator(() => ({
|
|
294
|
+
args: [pattern.source, pattern.flags],
|
|
295
|
+
kind: 'validatorjs',
|
|
296
|
+
validator: 'matches',
|
|
297
|
+
...resolvedOptions
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
return createValidationDecorator(() => ({
|
|
301
|
+
args: [pattern, typeof modifiersOrOptions === 'string' ? modifiersOrOptions : undefined].filter(value => value !== undefined),
|
|
302
|
+
kind: 'validatorjs',
|
|
303
|
+
validator: 'matches',
|
|
304
|
+
...resolvedOptions
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
307
|
+
export const IsAlpha = options => createValidatorJsDecorator('alpha')(undefined, options);
|
|
308
|
+
export const IsAlphanumeric = options => createValidatorJsDecorator('alphanumeric')(undefined, options);
|
|
309
|
+
export const IsAscii = options => createValidatorJsDecorator('ascii')(undefined, options);
|
|
310
|
+
export const IsBase64 = options => createValidatorJsDecorator('base64')(undefined, options);
|
|
311
|
+
export const IsBooleanString = options => createValidatorJsDecorator('booleanString')(undefined, options);
|
|
312
|
+
export const IsDataURI = options => createValidatorJsDecorator('dataURI')(undefined, options);
|
|
313
|
+
export const IsDateString = options => createValidatorJsDecorator('dateString')(undefined, options);
|
|
314
|
+
export const IsDecimal = options => createValidatorJsDecorator('decimal')(undefined, options);
|
|
315
|
+
export const IsEmail = options => createValidatorJsDecorator('email')(undefined, options);
|
|
316
|
+
export const IsFQDN = options => createValidatorJsDecorator('fqdn')(undefined, options);
|
|
317
|
+
export const IsHexColor = options => createValidatorJsDecorator('hexColor')(undefined, options);
|
|
318
|
+
export const IsHexadecimal = options => createValidatorJsDecorator('hexadecimal')(undefined, options);
|
|
319
|
+
export const IsJSON = options => createValidatorJsDecorator('json')(undefined, options);
|
|
320
|
+
export const IsJWT = options => createValidatorJsDecorator('jwt')(undefined, options);
|
|
321
|
+
export const IsLocale = options => createValidatorJsDecorator('locale')(undefined, options);
|
|
322
|
+
export const IsLowercase = options => createValidatorJsDecorator('lowercase')(undefined, options);
|
|
323
|
+
export const IsMagnetURI = options => createValidatorJsDecorator('magnetURI')(undefined, options);
|
|
324
|
+
export const IsMimeType = options => createValidatorJsDecorator('mimeType')(undefined, options);
|
|
325
|
+
export const IsMongoId = options => createValidatorJsDecorator('mongoId')(undefined, options);
|
|
326
|
+
export const IsNumberString = options => createValidatorJsDecorator('numberString')(undefined, options);
|
|
327
|
+
export const IsPort = options => createValidatorJsDecorator('port')(undefined, options);
|
|
328
|
+
export const IsRFC3339 = options => createValidatorJsDecorator('rfc3339')(undefined, options);
|
|
329
|
+
export const IsSemVer = options => createValidatorJsDecorator('semVer')(undefined, options);
|
|
330
|
+
export const IsUppercase = options => createValidatorJsDecorator('uppercase')(undefined, options);
|
|
331
|
+
export const IsISO8601 = options => createValidatorJsDecorator('iso8601')(undefined, options);
|
|
332
|
+
export const IsLatitude = options => createValidatorJsDecorator('latitude')(undefined, options);
|
|
333
|
+
export const IsLongitude = options => createValidatorJsDecorator('longitude')(undefined, options);
|
|
334
|
+
export const IsLatLong = options => createValidatorJsDecorator('latLong')(undefined, options);
|
|
335
|
+
|
|
336
|
+
/** Validates that a value is an IPv4/IPv6 address. */
|
|
337
|
+
export function IsIP(version, options) {
|
|
338
|
+
return createValidatorJsDecorator('ip')(version ? [version] : undefined, options);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** Validates that a value is an ISBN string. */
|
|
342
|
+
export function IsISBN(version, options) {
|
|
343
|
+
return createValidatorJsDecorator('isbn')(version ? [String(version)] : undefined, options);
|
|
344
|
+
}
|
|
345
|
+
export function IsISSN(options) {
|
|
346
|
+
return createValidatorJsDecorator('issn')(undefined, options);
|
|
347
|
+
}
|
|
348
|
+
export function IsMobilePhone(locale, options) {
|
|
349
|
+
return createValidatorJsDecorator('mobilePhone')(locale ? [locale] : undefined, options);
|
|
350
|
+
}
|
|
351
|
+
export function IsPostalCode(locale, options) {
|
|
352
|
+
return createValidatorJsDecorator('postalCode')(locale ? [locale] : undefined, options);
|
|
353
|
+
}
|
|
354
|
+
export function IsRgbColor(includePercentValues, options) {
|
|
355
|
+
return createValidatorJsDecorator('rgbColor')(includePercentValues === undefined ? undefined : [includePercentValues], options);
|
|
356
|
+
}
|
|
357
|
+
export function IsUrl(options) {
|
|
358
|
+
return createValidatorJsDecorator('url')(undefined, options);
|
|
359
|
+
}
|
|
360
|
+
export function IsUUID(version, options) {
|
|
361
|
+
return createValidatorJsDecorator('uuid')(version ? [version] : undefined, options);
|
|
362
|
+
}
|
|
363
|
+
export function IsCurrency(options) {
|
|
364
|
+
return createValidatorJsDecorator('currency')(undefined, options);
|
|
365
|
+
}
|
|
366
|
+
export const ArrayContains = createArrayValidationDecorator((values, options) => ({
|
|
367
|
+
kind: 'arrayContains',
|
|
368
|
+
values,
|
|
369
|
+
...options
|
|
370
|
+
}));
|
|
371
|
+
export const ArrayNotContains = createArrayValidationDecorator((values, options) => ({
|
|
372
|
+
kind: 'arrayNotContains',
|
|
373
|
+
values,
|
|
374
|
+
...options
|
|
375
|
+
}));
|
|
376
|
+
export const ArrayNotEmpty = createFlagValidationDecorator(options => ({
|
|
377
|
+
kind: 'arrayNotEmpty',
|
|
378
|
+
...options
|
|
379
|
+
}));
|
|
380
|
+
export const ArrayMinSize = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
381
|
+
kind: 'arrayMinSize',
|
|
382
|
+
value,
|
|
383
|
+
...options
|
|
384
|
+
}));
|
|
385
|
+
export const ArrayMaxSize = createValidationOptionsWithConfigDecorator((value, options) => ({
|
|
386
|
+
kind: 'arrayMaxSize',
|
|
387
|
+
value,
|
|
388
|
+
...options
|
|
389
|
+
}));
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Ensures all values in the array are unique, optionally by selector.
|
|
393
|
+
*
|
|
394
|
+
* @param selectorOrOptions Optional selector callback used to compute uniqueness keys, or validation options.
|
|
395
|
+
* @param options Validation options used when a selector callback is provided.
|
|
396
|
+
* @returns A field decorator that registers an array-uniqueness rule.
|
|
397
|
+
*/
|
|
398
|
+
export function ArrayUnique(selectorOrOptions, options) {
|
|
399
|
+
const selector = typeof selectorOrOptions === 'function' ? selectorOrOptions : undefined;
|
|
400
|
+
const resolvedOptions = typeof selectorOrOptions === 'function' ? options : selectorOrOptions;
|
|
401
|
+
return createValidationDecorator(() => ({
|
|
402
|
+
kind: 'arrayUnique',
|
|
403
|
+
selector,
|
|
404
|
+
...resolvedOptions
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Registers a custom field-level validation function.
|
|
410
|
+
*
|
|
411
|
+
* @param validate Custom validator callback invoked with `(dto, value)`.
|
|
412
|
+
* @param options Optional custom-validator metadata (`message`, `code`, `source`, `each`).
|
|
413
|
+
* @returns A field decorator that registers a custom validation rule.
|
|
414
|
+
*/
|
|
415
|
+
export function Validate(validate, options) {
|
|
416
|
+
return createValidationDecorator(() => ({
|
|
417
|
+
code: options?.code,
|
|
418
|
+
each: options?.each,
|
|
419
|
+
kind: 'custom',
|
|
420
|
+
message: options?.message,
|
|
421
|
+
source: options?.source,
|
|
422
|
+
validate
|
|
423
|
+
}));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Registers class-level validation logic.
|
|
428
|
+
* Supports either a custom validator callback or a Standard Schema object.
|
|
429
|
+
*
|
|
430
|
+
* @param validate Class-level validator callback or a Standard Schema-compatible validator definition.
|
|
431
|
+
* @param options Optional validation behavior (`message`, `code`).
|
|
432
|
+
* @returns A class decorator that appends class-level validation rules.
|
|
433
|
+
*/
|
|
434
|
+
export function ValidateClass(validate, options) {
|
|
435
|
+
const decorator = (_target, context) => {
|
|
436
|
+
appendStandardClassValidationRule(context.metadata, {
|
|
437
|
+
code: options?.code,
|
|
438
|
+
message: options?.message,
|
|
439
|
+
validate: resolveClassValidator(validate)
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
return decorator;
|
|
443
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE;gBAD3C,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,SAAS,eAAe,EAAE;CAM9C"}
|
package/dist/errors.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type Constructor } from '@fluojs/core';
|
|
2
|
+
type DtoConstructor<T = object> = Constructor<T>;
|
|
3
|
+
/**
|
|
4
|
+
* Derive a DTO class that keeps only the selected properties from a base DTO.
|
|
5
|
+
*
|
|
6
|
+
* Validation and binding metadata are copied only for the requested keys, which
|
|
7
|
+
* keeps request materialization aligned with the subset contract documented in
|
|
8
|
+
* the base DTO.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam TBase Base DTO constructor to derive from.
|
|
11
|
+
* @typeParam TKey String keys preserved on the derived DTO.
|
|
12
|
+
* @param BaseDto Source DTO that already declares binding and validation metadata.
|
|
13
|
+
* @param keys Property names to keep on the derived DTO.
|
|
14
|
+
* @returns A derived DTO constructor that materializes and validates only the selected fields.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* class UserDto {
|
|
19
|
+
* email = '';
|
|
20
|
+
* name = '';
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* class UserEmailDto extends PickType(UserDto, ['email']) {}
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function PickType<TBase extends DtoConstructor, TKey extends Extract<keyof InstanceType<TBase>, string>>(BaseDto: TBase, keys: readonly TKey[]): DtoConstructor<Pick<InstanceType<TBase>, TKey>>;
|
|
27
|
+
/**
|
|
28
|
+
* Derive a DTO class that removes specific properties from a base DTO.
|
|
29
|
+
*
|
|
30
|
+
* Binding and validation metadata for omitted properties are intentionally not
|
|
31
|
+
* copied, so downstream transports cannot bind or validate those fields on the
|
|
32
|
+
* derived contract.
|
|
33
|
+
*
|
|
34
|
+
* @typeParam TBase Base DTO constructor to derive from.
|
|
35
|
+
* @typeParam TKey String keys removed from the derived DTO.
|
|
36
|
+
* @param BaseDto Source DTO that already declares binding and validation metadata.
|
|
37
|
+
* @param keys Property names to exclude from the derived DTO.
|
|
38
|
+
* @returns A derived DTO constructor that preserves every base field except the omitted keys.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* class UserDto {
|
|
43
|
+
* id = '';
|
|
44
|
+
* passwordHash = '';
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* class PublicUserDto extends OmitType(UserDto, ['passwordHash']) {}
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function OmitType<TBase extends DtoConstructor, TKey extends Extract<keyof InstanceType<TBase>, string>>(BaseDto: TBase, keys: readonly TKey[]): DtoConstructor<Omit<InstanceType<TBase>, TKey>>;
|
|
51
|
+
type UnionToIntersection<T> = (T extends unknown ? (value: T) => void : never) extends (value: infer TResult) => void ? TResult : never;
|
|
52
|
+
type IntersectionInstance<TBaseDtos extends readonly DtoConstructor[]> = UnionToIntersection<InstanceType<TBaseDtos[number]>>;
|
|
53
|
+
/**
|
|
54
|
+
* Combine multiple DTO classes into one intersection DTO.
|
|
55
|
+
*
|
|
56
|
+
* The derived constructor initializes every property discovered across the
|
|
57
|
+
* source DTOs and copies each source DTO's binding and validation metadata.
|
|
58
|
+
*
|
|
59
|
+
* @typeParam TBaseDtos Tuple of DTO constructors to merge.
|
|
60
|
+
* @param baseDtos DTO constructors whose fields and rules should be combined.
|
|
61
|
+
* @returns A DTO constructor whose instance type is the intersection of every input DTO.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* class PaginationDto {
|
|
66
|
+
* page = 1;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* class SearchDto {
|
|
70
|
+
* query = '';
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* class SearchPageDto extends IntersectionType(PaginationDto, SearchDto) {}
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function IntersectionType<TBaseDtos extends readonly [DtoConstructor, DtoConstructor, ...DtoConstructor[]]>(...baseDtos: TBaseDtos): DtoConstructor<IntersectionInstance<TBaseDtos>>;
|
|
77
|
+
/**
|
|
78
|
+
* Derive a DTO class where every bound field from the base DTO becomes optional.
|
|
79
|
+
*
|
|
80
|
+
* Existing validators are preserved, and an `optional` validation rule is added
|
|
81
|
+
* when the base field did not already declare one.
|
|
82
|
+
*
|
|
83
|
+
* @typeParam TBase Base DTO constructor to derive from.
|
|
84
|
+
* @param BaseDto Source DTO that defines the original field contract.
|
|
85
|
+
* @returns A derived DTO constructor suited for patch/update style payloads.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* class CreateUserDto {
|
|
90
|
+
* email = '';
|
|
91
|
+
* name = '';
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* class UpdateUserDto extends PartialType(CreateUserDto) {}
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function PartialType<TBase extends DtoConstructor>(BaseDto: TBase): DtoConstructor<Partial<InstanceType<TBase>>>;
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=mapped-types.d.ts.map
|
|
@@ -0,0 +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;AAiEjD;;;;;;;;;;;;;;;;;;;;;;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,CAkCtH"}
|