@rtpaulino/entity 0.14.0 → 0.14.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/dist/lib/entity-utils.d.ts +10 -9
- package/dist/lib/entity-utils.d.ts.map +1 -1
- package/dist/lib/entity-utils.js +35 -26
- package/dist/lib/entity-utils.js.map +1 -1
- package/dist/lib/problem.d.ts +1 -4
- package/dist/lib/problem.d.ts.map +1 -1
- package/dist/lib/problem.js +1 -1
- package/dist/lib/problem.js.map +1 -1
- package/dist/lib/types.d.ts +14 -12
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -94,7 +94,7 @@ export declare class EntityUtils {
|
|
|
94
94
|
* @param entityClass - The entity class constructor. Must accept a data object parameter.
|
|
95
95
|
* @param plainObject - The plain object to deserialize
|
|
96
96
|
* @param options - Parse options (strict mode)
|
|
97
|
-
* @returns
|
|
97
|
+
* @returns Promise resolving to a new instance of the entity with deserialized values
|
|
98
98
|
*
|
|
99
99
|
* @remarks
|
|
100
100
|
* Deserialization rules:
|
|
@@ -111,6 +111,7 @@ export declare class EntityUtils {
|
|
|
111
111
|
* - If strict: true - both HARD and SOFT problems throw ValidationError
|
|
112
112
|
* - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored
|
|
113
113
|
* - Property validators run first, then entity validators
|
|
114
|
+
* - Validators can be synchronous or asynchronous
|
|
114
115
|
* - Problems are accessible via EntityUtils.problems()
|
|
115
116
|
* - Raw input data is accessible via EntityUtils.getRawInput()
|
|
116
117
|
*
|
|
@@ -127,13 +128,13 @@ export declare class EntityUtils {
|
|
|
127
128
|
* }
|
|
128
129
|
*
|
|
129
130
|
* const json = { name: 'John', age: 30 };
|
|
130
|
-
* const user = EntityUtils.parse(User, json);
|
|
131
|
-
* const userStrict = EntityUtils.parse(User, json, { strict: true });
|
|
131
|
+
* const user = await EntityUtils.parse(User, json);
|
|
132
|
+
* const userStrict = await EntityUtils.parse(User, json, { strict: true });
|
|
132
133
|
* ```
|
|
133
134
|
*/
|
|
134
|
-
static parse<T extends object>(entityClass: new (data: any) => T, plainObject:
|
|
135
|
+
static parse<T extends object>(entityClass: new (data: any) => T, plainObject: unknown, options?: {
|
|
135
136
|
strict?: boolean;
|
|
136
|
-
}): T
|
|
137
|
+
}): Promise<T>;
|
|
137
138
|
/**
|
|
138
139
|
* Deserializes a single value according to the type metadata
|
|
139
140
|
* @private
|
|
@@ -160,21 +161,21 @@ export declare class EntityUtils {
|
|
|
160
161
|
* Validates an entity instance by running all property and entity validators
|
|
161
162
|
*
|
|
162
163
|
* @param instance - The entity instance to validate
|
|
163
|
-
* @returns
|
|
164
|
+
* @returns Promise resolving to array of Problems found during validation (empty if valid)
|
|
164
165
|
*
|
|
165
166
|
* @remarks
|
|
166
167
|
* - Property validators run first, then entity validators
|
|
167
|
-
* - Each validator
|
|
168
|
+
* - Each validator can be synchronous or asynchronous
|
|
168
169
|
* - Empty array means no problems found
|
|
169
170
|
*
|
|
170
171
|
* @example
|
|
171
172
|
* ```typescript
|
|
172
173
|
* const user = new User({ name: '', age: -5 });
|
|
173
|
-
* const problems = EntityUtils.validate(user);
|
|
174
|
+
* const problems = await EntityUtils.validate(user);
|
|
174
175
|
* console.log(problems); // [Problem, Problem, ...]
|
|
175
176
|
* ```
|
|
176
177
|
*/
|
|
177
|
-
static validate<T extends object>(instance: T): Problem[]
|
|
178
|
+
static validate<T extends object>(instance: T): Promise<Problem[]>;
|
|
178
179
|
/**
|
|
179
180
|
* Gets the validation problems for an entity instance
|
|
180
181
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,eAAe,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuBvC,qBAAa,WAAW;IACtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM;IAmB5C,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAQhD,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAoChD,MAAM,CAAC,kBAAkB,CACvB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,eAAe,GAAG,SAAS;IA8B9B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO;IA2B9C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,MAAM,EAC1B,SAAS,EAAE,CAAC,EACZ,SAAS,EAAE,CAAC,GACX;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE;IAoC/D,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAaxE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAmBnE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAsD7B
|
|
1
|
+
{"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,eAAe,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuBvC,qBAAa,WAAW;IACtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM;IAmB5C,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAQhD,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAoChD,MAAM,CAAC,kBAAkB,CACvB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,eAAe,GAAG,SAAS;IA8B9B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO;IA2B9C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,MAAM,EAC1B,SAAS,EAAE,CAAC,EACZ,SAAS,EAAE,CAAC,GACX;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE;IAoC/D,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAaxE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiDG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAmBnE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAsD7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;WACU,KAAK,CAAC,CAAC,SAAS,MAAM,EACjC,WAAW,EAAE,KAAK,IAAI,EAAE,GAAG,KAAK,CAAC,EACjC,WAAW,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,OAAO,CAAC,CAAC,CAAC;IA8Gb;;;OAGG;mBACkB,gBAAgB;IAiErC;;;;OAIG;mBACkB,sBAAsB;IA0B3C;;;;OAIG;mBACkB,qBAAqB;IAkC1C;;;OAGG;mBACkB,qBAAqB;IAoD1C;;;;;;;;;;;;;;;;;OAiBG;WACU,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAkCxE;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,EAAE;IAIzD;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,MAAM,EACjC,QAAQ,EAAE,CAAC,GACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAItC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;CA6BnC"}
|
package/dist/lib/entity-utils.js
CHANGED
|
@@ -262,7 +262,7 @@ export class EntityUtils {
|
|
|
262
262
|
* @param entityClass - The entity class constructor. Must accept a data object parameter.
|
|
263
263
|
* @param plainObject - The plain object to deserialize
|
|
264
264
|
* @param options - Parse options (strict mode)
|
|
265
|
-
* @returns
|
|
265
|
+
* @returns Promise resolving to a new instance of the entity with deserialized values
|
|
266
266
|
*
|
|
267
267
|
* @remarks
|
|
268
268
|
* Deserialization rules:
|
|
@@ -279,6 +279,7 @@ export class EntityUtils {
|
|
|
279
279
|
* - If strict: true - both HARD and SOFT problems throw ValidationError
|
|
280
280
|
* - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored
|
|
281
281
|
* - Property validators run first, then entity validators
|
|
282
|
+
* - Validators can be synchronous or asynchronous
|
|
282
283
|
* - Problems are accessible via EntityUtils.problems()
|
|
283
284
|
* - Raw input data is accessible via EntityUtils.getRawInput()
|
|
284
285
|
*
|
|
@@ -295,10 +296,19 @@ export class EntityUtils {
|
|
|
295
296
|
* }
|
|
296
297
|
*
|
|
297
298
|
* const json = { name: 'John', age: 30 };
|
|
298
|
-
* const user = EntityUtils.parse(User, json);
|
|
299
|
-
* const userStrict = EntityUtils.parse(User, json, { strict: true });
|
|
299
|
+
* const user = await EntityUtils.parse(User, json);
|
|
300
|
+
* const userStrict = await EntityUtils.parse(User, json, { strict: true });
|
|
300
301
|
* ```
|
|
301
|
-
*/ static parse(entityClass, plainObject, options) {
|
|
302
|
+
*/ static async parse(entityClass, plainObject, options) {
|
|
303
|
+
if (plainObject == null) {
|
|
304
|
+
throw createValidationError(`Expects an object but received ${typeof plainObject}`);
|
|
305
|
+
}
|
|
306
|
+
if (Array.isArray(plainObject)) {
|
|
307
|
+
throw createValidationError(`Expects an object but received array`);
|
|
308
|
+
}
|
|
309
|
+
if (typeof plainObject !== 'object') {
|
|
310
|
+
throw createValidationError(`Expects an object but received ${typeof plainObject}`);
|
|
311
|
+
}
|
|
302
312
|
const strict = options?.strict ?? false;
|
|
303
313
|
const keys = this.getPropertyKeys(entityClass.prototype);
|
|
304
314
|
const data = {};
|
|
@@ -312,12 +322,11 @@ export class EntityUtils {
|
|
|
312
322
|
}));
|
|
313
323
|
continue;
|
|
314
324
|
}
|
|
325
|
+
const value = plainObject[key];
|
|
315
326
|
if (propertyOptions.passthrough === true) {
|
|
316
|
-
const value = plainObject[key];
|
|
317
327
|
data[key] = value;
|
|
318
328
|
continue;
|
|
319
329
|
}
|
|
320
|
-
const value = plainObject[key];
|
|
321
330
|
const isOptional = propertyOptions.optional === true;
|
|
322
331
|
if (!(key in plainObject)) {
|
|
323
332
|
if (!isOptional) {
|
|
@@ -339,7 +348,7 @@ export class EntityUtils {
|
|
|
339
348
|
continue;
|
|
340
349
|
}
|
|
341
350
|
try {
|
|
342
|
-
data[key] = this.deserializeValue(value, propertyOptions);
|
|
351
|
+
data[key] = await this.deserializeValue(value, propertyOptions);
|
|
343
352
|
} catch (error) {
|
|
344
353
|
if (error instanceof ValidationError) {
|
|
345
354
|
const problems = prependPropertyPath(key, error);
|
|
@@ -359,7 +368,7 @@ export class EntityUtils {
|
|
|
359
368
|
}
|
|
360
369
|
const instance = new entityClass(data);
|
|
361
370
|
rawInputStorage.set(instance, plainObject);
|
|
362
|
-
const problems = this.validate(instance);
|
|
371
|
+
const problems = await this.validate(instance);
|
|
363
372
|
if (problems.length > 0) {
|
|
364
373
|
if (strict) {
|
|
365
374
|
throw new ValidationError(problems);
|
|
@@ -372,7 +381,7 @@ export class EntityUtils {
|
|
|
372
381
|
/**
|
|
373
382
|
* Deserializes a single value according to the type metadata
|
|
374
383
|
* @private
|
|
375
|
-
*/ static deserializeValue(value, options) {
|
|
384
|
+
*/ static async deserializeValue(value, options) {
|
|
376
385
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
377
386
|
const typeConstructor = options.type();
|
|
378
387
|
const isArray = options.array === true;
|
|
@@ -398,7 +407,7 @@ export class EntityUtils {
|
|
|
398
407
|
if (options.deserialize) {
|
|
399
408
|
result.push(options.deserialize(item));
|
|
400
409
|
} else {
|
|
401
|
-
result.push(this.deserializeSingleValue(item, typeConstructor));
|
|
410
|
+
result.push(await this.deserializeSingleValue(item, typeConstructor));
|
|
402
411
|
}
|
|
403
412
|
} catch (error) {
|
|
404
413
|
if (error instanceof ValidationError) {
|
|
@@ -418,13 +427,13 @@ export class EntityUtils {
|
|
|
418
427
|
if (options.deserialize) {
|
|
419
428
|
return options.deserialize(value);
|
|
420
429
|
}
|
|
421
|
-
return this.deserializeSingleValue(value, typeConstructor);
|
|
430
|
+
return await this.deserializeSingleValue(value, typeConstructor);
|
|
422
431
|
}
|
|
423
432
|
/**
|
|
424
433
|
* Deserializes a single non-array value
|
|
425
434
|
* Reports validation errors with empty property (caller will prepend context)
|
|
426
435
|
* @private
|
|
427
|
-
*/ static deserializeSingleValue(value, typeConstructor) {
|
|
436
|
+
*/ static async deserializeSingleValue(value, typeConstructor) {
|
|
428
437
|
if (isPrimitiveConstructor(typeConstructor)) {
|
|
429
438
|
return deserializePrimitive(value, typeConstructor);
|
|
430
439
|
}
|
|
@@ -432,7 +441,7 @@ export class EntityUtils {
|
|
|
432
441
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
433
442
|
throw createValidationError(`Expects an object but received ${typeof value}`);
|
|
434
443
|
}
|
|
435
|
-
return this.parse(typeConstructor, value);
|
|
444
|
+
return await this.parse(typeConstructor, value);
|
|
436
445
|
}
|
|
437
446
|
throw createValidationError(`Has unknown type constructor. Supported types are: String, Number, Boolean, Date, BigInt, and @Entity() classes. Use passthrough: true to explicitly allow unknown types.`);
|
|
438
447
|
}
|
|
@@ -440,11 +449,11 @@ export class EntityUtils {
|
|
|
440
449
|
* Validates a property value by running validators and nested entity validation.
|
|
441
450
|
* Prepends the property path to all returned problems.
|
|
442
451
|
* @private
|
|
443
|
-
*/ static validatePropertyValue(propertyPath, value, validators) {
|
|
452
|
+
*/ static async validatePropertyValue(propertyPath, value, validators) {
|
|
444
453
|
const problems = [];
|
|
445
454
|
if (validators) {
|
|
446
455
|
for (const validator of validators){
|
|
447
|
-
const validatorProblems = validator({
|
|
456
|
+
const validatorProblems = await validator({
|
|
448
457
|
value
|
|
449
458
|
});
|
|
450
459
|
// Prepend propertyPath to all problems
|
|
@@ -457,7 +466,7 @@ export class EntityUtils {
|
|
|
457
466
|
}
|
|
458
467
|
}
|
|
459
468
|
if (EntityUtils.isEntity(value)) {
|
|
460
|
-
const nestedProblems = EntityUtils.validate(value);
|
|
469
|
+
const nestedProblems = await EntityUtils.validate(value);
|
|
461
470
|
const prependedProblems = prependPropertyPath(propertyPath, new ValidationError(nestedProblems));
|
|
462
471
|
problems.push(...prependedProblems);
|
|
463
472
|
}
|
|
@@ -466,18 +475,18 @@ export class EntityUtils {
|
|
|
466
475
|
/**
|
|
467
476
|
* Runs property validators for a given property value
|
|
468
477
|
* @private
|
|
469
|
-
*/ static runPropertyValidators(key, value, options) {
|
|
478
|
+
*/ static async runPropertyValidators(key, value, options) {
|
|
470
479
|
const problems = [];
|
|
471
480
|
const isArray = options?.array === true;
|
|
472
481
|
const isPassthrough = options?.passthrough === true;
|
|
473
482
|
if (isPassthrough || !isArray) {
|
|
474
|
-
const valueProblems = this.validatePropertyValue(key, value, options.validators);
|
|
483
|
+
const valueProblems = await this.validatePropertyValue(key, value, options.validators);
|
|
475
484
|
problems.push(...valueProblems);
|
|
476
485
|
} else {
|
|
477
486
|
ok(Array.isArray(value), 'Value must be an array for array property');
|
|
478
487
|
const arrayValidators = options.arrayValidators || [];
|
|
479
488
|
for (const validator of arrayValidators){
|
|
480
|
-
const validatorProblems = validator({
|
|
489
|
+
const validatorProblems = await validator({
|
|
481
490
|
value
|
|
482
491
|
});
|
|
483
492
|
for (const problem of validatorProblems){
|
|
@@ -493,7 +502,7 @@ export class EntityUtils {
|
|
|
493
502
|
const element = value[i];
|
|
494
503
|
if (element !== null && element !== undefined) {
|
|
495
504
|
const elementPath = `${key}[${i}]`;
|
|
496
|
-
const elementProblems = this.validatePropertyValue(elementPath, element, validators);
|
|
505
|
+
const elementProblems = await this.validatePropertyValue(elementPath, element, validators);
|
|
497
506
|
problems.push(...elementProblems);
|
|
498
507
|
}
|
|
499
508
|
}
|
|
@@ -505,20 +514,20 @@ export class EntityUtils {
|
|
|
505
514
|
* Validates an entity instance by running all property and entity validators
|
|
506
515
|
*
|
|
507
516
|
* @param instance - The entity instance to validate
|
|
508
|
-
* @returns
|
|
517
|
+
* @returns Promise resolving to array of Problems found during validation (empty if valid)
|
|
509
518
|
*
|
|
510
519
|
* @remarks
|
|
511
520
|
* - Property validators run first, then entity validators
|
|
512
|
-
* - Each validator
|
|
521
|
+
* - Each validator can be synchronous or asynchronous
|
|
513
522
|
* - Empty array means no problems found
|
|
514
523
|
*
|
|
515
524
|
* @example
|
|
516
525
|
* ```typescript
|
|
517
526
|
* const user = new User({ name: '', age: -5 });
|
|
518
|
-
* const problems = EntityUtils.validate(user);
|
|
527
|
+
* const problems = await EntityUtils.validate(user);
|
|
519
528
|
* console.log(problems); // [Problem, Problem, ...]
|
|
520
529
|
* ```
|
|
521
|
-
*/ static validate(instance) {
|
|
530
|
+
*/ static async validate(instance) {
|
|
522
531
|
if (!this.isEntity(instance)) {
|
|
523
532
|
throw new Error('Cannot validate non-entity instance');
|
|
524
533
|
}
|
|
@@ -529,14 +538,14 @@ export class EntityUtils {
|
|
|
529
538
|
if (options) {
|
|
530
539
|
const value = instance[key];
|
|
531
540
|
if (value != null) {
|
|
532
|
-
const validationProblems = this.runPropertyValidators(key, value, options);
|
|
541
|
+
const validationProblems = await this.runPropertyValidators(key, value, options);
|
|
533
542
|
problems.push(...validationProblems);
|
|
534
543
|
}
|
|
535
544
|
}
|
|
536
545
|
}
|
|
537
546
|
const entityValidators = this.getEntityValidators(instance);
|
|
538
547
|
for (const validatorMethod of entityValidators){
|
|
539
|
-
const validatorProblems = instance[validatorMethod]();
|
|
548
|
+
const validatorProblems = await instance[validatorMethod]();
|
|
540
549
|
if (Array.isArray(validatorProblems)) {
|
|
541
550
|
problems.push(...validatorProblems);
|
|
542
551
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/entity-utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n} from './types.js';\nimport { isEqualWith } from 'lodash-es';\nimport { ValidationError } from './validation-error.js';\nimport { Problem } from './problem.js';\nimport {\n prependPropertyPath,\n prependArrayIndex,\n createValidationError,\n combinePropertyPaths,\n} from './validation-utils.js';\nimport {\n isPrimitiveConstructor,\n deserializePrimitive,\n} from './primitive-deserializers.js';\nimport { ok } from 'assert';\n\n/**\n * WeakMap to store validation problems for entity instances\n */\nconst problemsStorage = new WeakMap<object, Problem[]>();\n\n/**\n * WeakMap to store raw input data for entity instances\n */\nconst rawInputStorage = new WeakMap<object, Record<string, unknown>>();\n\nexport class EntityUtils {\n /**\n * Checks if a given object is an instance of a class decorated with @Entity()\n * or if the provided value is an entity class itself\n *\n * @param obj - The object or class to check\n * @returns true if the object is an entity instance or entity class, false otherwise\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * name: string;\n * }\n *\n * const user = new User();\n * console.log(EntityUtils.isEntity(user)); // true\n * console.log(EntityUtils.isEntity(User)); // true\n * console.log(EntityUtils.isEntity({})); // false\n * ```\n */\n static isEntity(obj: unknown): obj is object {\n if (obj == null) {\n return false;\n }\n\n // Check if obj is a constructor function (class)\n if (typeof obj === 'function') {\n return Reflect.hasMetadata(ENTITY_METADATA_KEY, obj);\n }\n\n // Check if obj is an object instance\n if (typeof obj !== 'object' || Array.isArray(obj)) {\n return false;\n }\n\n const constructor = Object.getPrototypeOf(obj).constructor;\n return Reflect.hasMetadata(ENTITY_METADATA_KEY, constructor);\n }\n\n static sameEntity(a: object, b: object): boolean {\n if (!this.isEntity(a) || !this.isEntity(b)) {\n return false;\n }\n\n return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);\n }\n\n static getPropertyKeys(target: object): string[] {\n // Determine if we're dealing with a prototype or an instance\n let currentProto: any;\n\n // Check if target is a prototype by checking if it has a constructor property\n // and if target === target.constructor.prototype\n if (target.constructor && target === target.constructor.prototype) {\n // target is already a prototype\n currentProto = target;\n } else {\n // target is an instance, get its prototype\n currentProto = Object.getPrototypeOf(target);\n }\n\n const keys: string[] = [];\n const seen = new Set<string>();\n\n // Walk the prototype chain to collect all inherited properties\n while (currentProto && currentProto !== Object.prototype) {\n // Use getOwnMetadata to only get metadata directly on this prototype\n const protoKeys: string[] =\n Reflect.getOwnMetadata(PROPERTY_METADATA_KEY, currentProto) || [];\n\n for (const key of protoKeys) {\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return keys;\n }\n\n static getPropertyOptions(\n target: object,\n propertyKey: string,\n ): PropertyOptions | undefined {\n // Determine if we're dealing with a prototype or an instance\n let currentProto: any;\n\n // Check if target is a prototype by checking if it has a constructor property\n // and if target === target.constructor.prototype\n if (target.constructor && target === target.constructor.prototype) {\n // target is already a prototype\n currentProto = target;\n } else {\n // target is an instance, get its prototype\n currentProto = Object.getPrototypeOf(target);\n }\n\n // Walk the prototype chain to find the property options\n while (currentProto && currentProto !== Object.prototype) {\n const protoOptions: Record<string, PropertyOptions> =\n Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, currentProto) ||\n {};\n\n if (protoOptions[propertyKey]) {\n return protoOptions[propertyKey];\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return undefined;\n }\n\n static equals(a: unknown, b: unknown): boolean {\n return isEqualWith(a, b, (val1, val2) => {\n if (this.isEntity(val1)) {\n if (!this.sameEntity(val1, val2)) {\n return false;\n }\n\n const diff = this.diff(val1, val2);\n\n return diff.length === 0;\n } else if (\n val1 != null &&\n val2 != null &&\n typeof val1 === 'object' &&\n !Array.isArray(val1) &&\n typeof val2 === 'object' &&\n !Array.isArray(val2) &&\n 'equals' in val1 &&\n typeof val1.equals === 'function'\n ) {\n return val1.equals(val2);\n }\n\n return undefined;\n });\n }\n\n static diff<T extends object>(\n oldEntity: T,\n newEntity: T,\n ): { property: string; oldValue: unknown; newValue: unknown }[] {\n if (!this.sameEntity(oldEntity, newEntity)) {\n throw new Error('Entities must be of the same type to compute diff');\n }\n\n const diffs: { property: string; oldValue: unknown; newValue: unknown }[] =\n [];\n\n const keys = this.getPropertyKeys(oldEntity);\n\n for (const key of keys) {\n const oldValue = (oldEntity as any)[key];\n const newValue = (newEntity as any)[key];\n\n // Check if there's a custom equals function for this property\n const propertyOptions = this.getPropertyOptions(oldEntity, key);\n\n let areEqual: boolean;\n if (oldValue == null && newValue == null) {\n areEqual = oldValue === newValue;\n } else if (oldValue == null || newValue == null) {\n areEqual = false;\n } else {\n areEqual = propertyOptions?.equals\n ? propertyOptions.equals(oldValue, newValue)\n : this.equals(oldValue, newValue);\n }\n\n if (!areEqual) {\n diffs.push({ property: key, oldValue, newValue });\n }\n }\n\n return diffs;\n }\n\n static changes<T extends object>(oldEntity: T, newEntity: T): Partial<T> {\n if (!this.sameEntity(oldEntity, newEntity)) {\n throw new Error('Entities must be of the same type to compute changes');\n }\n\n const diff = this.diff(oldEntity, newEntity);\n\n return diff.reduce((acc, { property, newValue }) => {\n (acc as any)[property] = newValue;\n return acc;\n }, {} as Partial<T>);\n }\n\n /**\n * Serializes an entity to a plain object, converting only properties decorated with @Property()\n *\n * @param entity - The entity instance to serialize\n * @returns A plain object containing only the serialized decorated properties\n *\n * @remarks\n * Serialization rules:\n * - Only properties decorated with @Property() are included\n * - If a property has a custom toJSON() method, it will be used\n * - Nested entities are recursively serialized using EntityUtils.toJSON()\n * - Arrays are mapped with toJSON() applied to each element\n * - Date objects are serialized to ISO strings\n * - bigint values are serialized to strings\n * - undefined values are excluded from the output\n * - null values are included in the output\n * - Circular references are not supported (will cause stack overflow)\n *\n * @example\n * ```typescript\n * @Entity()\n * class Address {\n * @Property() street: string;\n * @Property() city: string;\n * }\n *\n * @Entity()\n * class User {\n * @Property() name: string;\n * @Property() address: Address;\n * @Property() createdAt: Date;\n * undecorated: string; // Will not be serialized\n * }\n *\n * const user = new User();\n * user.name = 'John';\n * user.address = new Address();\n * user.address.street = '123 Main St';\n * user.address.city = 'Boston';\n * user.createdAt = new Date('2024-01-01');\n * user.undecorated = 'ignored';\n *\n * const json = EntityUtils.toJSON(user);\n * // {\n * // name: 'John',\n * // address: { street: '123 Main St', city: 'Boston' },\n * // createdAt: '2024-01-01T00:00:00.000Z'\n * // }\n * ```\n */\n static toJSON<T extends object>(entity: T): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const keys = this.getPropertyKeys(entity);\n\n for (const key of keys) {\n const value = (entity as any)[key];\n\n // Skip undefined values\n if (value === undefined) {\n continue;\n }\n\n const options = this.getPropertyOptions(entity, key);\n result[key] = this.serializeValue(value, options);\n }\n\n return result;\n }\n\n /**\n * Serializes a single value according to the toJSON rules\n * @private\n */\n private static serializeValue(\n value: unknown,\n options?: PropertyOptions,\n ): unknown {\n if (value === null) {\n return null;\n }\n\n if (value === undefined) {\n return undefined;\n }\n\n const passthrough = options?.passthrough === true;\n if (passthrough) {\n return value;\n }\n\n if (Array.isArray(value)) {\n if (options?.serialize) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return value.map((item) => options.serialize!(item as any));\n }\n return value.map((item) => this.serializeValue(item));\n }\n\n if (options?.serialize) {\n return options.serialize(value as any);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (this.isEntity(value)) {\n return this.toJSON(value);\n }\n\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n\n throw new Error(\n `Cannot serialize value of type '${typeof value}'. Use passthrough: true in @Property() to explicitly allow serialization of unknown types.`,\n );\n }\n\n /**\n * Deserializes a plain object to an entity instance\n *\n * @param entityClass - The entity class constructor. Must accept a data object parameter.\n * @param plainObject - The plain object to deserialize\n * @param options - Parse options (strict mode)\n * @returns A new instance of the entity with deserialized values\n *\n * @remarks\n * Deserialization rules:\n * - All @Property() decorators must include type metadata for parse() to work\n * - Properties without type metadata will throw an error\n * - Required properties (optional !== true) must be present and not null/undefined\n * - Optional properties (optional === true) can be undefined or null\n * - Arrays are supported with the array: true option\n * - Nested entities are recursively deserialized\n * - Type conversion is strict (no coercion)\n * - Entity constructors must accept a required data parameter\n *\n * Validation behavior:\n * - If strict: true - both HARD and SOFT problems throw ValidationError\n * - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored\n * - Property validators run first, then entity validators\n * - Problems are accessible via EntityUtils.problems()\n * - Raw input data is accessible via EntityUtils.getRawInput()\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n * @Property({ type: () => Number }) age!: number;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const json = { name: 'John', age: 30 };\n * const user = EntityUtils.parse(User, json);\n * const userStrict = EntityUtils.parse(User, json, { strict: true });\n * ```\n */\n static parse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: Record<string, unknown>,\n options?: { strict?: boolean },\n ): T {\n const strict = options?.strict ?? false;\n const keys = this.getPropertyKeys(entityClass.prototype);\n const data: Record<string, unknown> = {};\n const hardProblems: Problem[] = [];\n\n for (const key of keys) {\n const propertyOptions = this.getPropertyOptions(\n entityClass.prototype,\n key,\n );\n\n if (!propertyOptions) {\n hardProblems.push(\n new Problem({\n property: key,\n message: `Property has no metadata. This should not happen if @Property() was used correctly.`,\n }),\n );\n continue;\n }\n\n if (propertyOptions.passthrough === true) {\n const value = plainObject[key];\n data[key] = value;\n continue;\n }\n\n const value = plainObject[key];\n const isOptional = propertyOptions.optional === true;\n\n if (!(key in plainObject)) {\n if (!isOptional) {\n hardProblems.push(\n new Problem({\n property: key,\n message: 'Required property is missing from input',\n }),\n );\n }\n continue;\n }\n\n if (value === null || value === undefined) {\n if (!isOptional) {\n hardProblems.push(\n new Problem({\n property: key,\n message: 'Cannot be null or undefined',\n }),\n );\n }\n data[key] = value;\n continue;\n }\n\n try {\n data[key] = this.deserializeValue(value, propertyOptions);\n } catch (error) {\n if (error instanceof ValidationError) {\n const problems = prependPropertyPath(key, error);\n hardProblems.push(...problems);\n } else if (error instanceof Error) {\n hardProblems.push(\n new Problem({\n property: key,\n message: error.message,\n }),\n );\n } else {\n throw error;\n }\n }\n }\n\n if (hardProblems.length > 0) {\n throw new ValidationError(hardProblems);\n }\n\n const instance = new entityClass(data);\n\n rawInputStorage.set(instance, plainObject);\n\n const problems = this.validate(instance);\n\n if (problems.length > 0) {\n if (strict) {\n throw new ValidationError(problems);\n } else {\n problemsStorage.set(instance, problems);\n }\n }\n\n return instance;\n }\n\n /**\n * Deserializes a single value according to the type metadata\n * @private\n */\n private static deserializeValue(\n value: unknown,\n options: PropertyOptions,\n ): unknown {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\n const isArray = options.array === true;\n const isSparse = options.sparse === true;\n\n if (isArray) {\n if (!Array.isArray(value)) {\n throw createValidationError(\n `Expects an array but received ${typeof value}`,\n );\n }\n\n const arrayProblems: Problem[] = [];\n const result: unknown[] = [];\n\n for (let index = 0; index < value.length; index++) {\n const item = value[index];\n if (item === null || item === undefined) {\n if (!isSparse) {\n arrayProblems.push(\n new Problem({\n property: `[${index}]`,\n message: 'Cannot be null or undefined.',\n }),\n );\n }\n result.push(item);\n } else {\n try {\n if (options.deserialize) {\n result.push(options.deserialize(item));\n } else {\n result.push(this.deserializeSingleValue(item, typeConstructor));\n }\n } catch (error) {\n if (error instanceof ValidationError) {\n const problems = prependArrayIndex(index, error);\n arrayProblems.push(...problems);\n } else {\n throw error;\n }\n }\n }\n }\n\n if (arrayProblems.length > 0) {\n throw new ValidationError(arrayProblems);\n }\n\n return result;\n }\n\n if (options.deserialize) {\n return options.deserialize(value);\n }\n\n return this.deserializeSingleValue(value, typeConstructor);\n }\n\n /**\n * Deserializes a single non-array value\n * Reports validation errors with empty property (caller will prepend context)\n * @private\n */\n private static deserializeSingleValue(\n value: unknown,\n typeConstructor: any,\n ): unknown {\n if (isPrimitiveConstructor(typeConstructor)) {\n return deserializePrimitive(value, typeConstructor);\n }\n\n if (this.isEntity(typeConstructor)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw createValidationError(\n `Expects an object but received ${typeof value}`,\n );\n }\n\n return this.parse(\n typeConstructor as new (data: any) => object,\n value as Record<string, unknown>,\n );\n }\n\n throw createValidationError(\n `Has unknown type constructor. Supported types are: String, Number, Boolean, Date, BigInt, and @Entity() classes. Use passthrough: true to explicitly allow unknown types.`,\n );\n }\n\n /**\n * Validates a property value by running validators and nested entity validation.\n * Prepends the property path to all returned problems.\n * @private\n */\n private static validatePropertyValue(\n propertyPath: string,\n value: unknown,\n validators: PropertyOptions['validators'],\n ): Problem[] {\n const problems: Problem[] = [];\n\n if (validators) {\n for (const validator of validators) {\n const validatorProblems = validator({ value });\n // Prepend propertyPath to all problems\n for (const problem of validatorProblems) {\n problems.push(\n new Problem({\n property: combinePropertyPaths(propertyPath, problem.property),\n message: problem.message,\n }),\n );\n }\n }\n }\n\n if (EntityUtils.isEntity(value)) {\n const nestedProblems = EntityUtils.validate(value);\n const prependedProblems = prependPropertyPath(\n propertyPath,\n new ValidationError(nestedProblems),\n );\n problems.push(...prependedProblems);\n }\n\n return problems;\n }\n\n /**\n * Runs property validators for a given property value\n * @private\n */\n private static runPropertyValidators(\n key: string,\n value: unknown,\n options: PropertyOptions,\n ): Problem[] {\n const problems: Problem[] = [];\n const isArray = options?.array === true;\n const isPassthrough = options?.passthrough === true;\n\n if (isPassthrough || !isArray) {\n const valueProblems = this.validatePropertyValue(\n key,\n value,\n options.validators,\n );\n problems.push(...valueProblems);\n } else {\n ok(Array.isArray(value), 'Value must be an array for array property');\n\n const arrayValidators = options.arrayValidators || [];\n for (const validator of arrayValidators) {\n const validatorProblems = validator({ value });\n for (const problem of validatorProblems) {\n problems.push(\n new Problem({\n property: combinePropertyPaths(key, problem.property),\n message: problem.message,\n }),\n );\n }\n }\n\n const validators = options.validators || [];\n if (validators.length > 0) {\n for (let i = 0; i < value.length; i++) {\n const element = value[i];\n if (element !== null && element !== undefined) {\n const elementPath = `${key}[${i}]`;\n const elementProblems = this.validatePropertyValue(\n elementPath,\n element,\n validators,\n );\n problems.push(...elementProblems);\n }\n }\n }\n }\n\n return problems;\n }\n\n /**\n * Validates an entity instance by running all property and entity validators\n *\n * @param instance - The entity instance to validate\n * @returns Array of Problems found during validation (empty if valid)\n *\n * @remarks\n * - Property validators run first, then entity validators\n * - Each validator returns an array of Problems\n * - Empty array means no problems found\n *\n * @example\n * ```typescript\n * const user = new User({ name: '', age: -5 });\n * const problems = EntityUtils.validate(user);\n * console.log(problems); // [Problem, Problem, ...]\n * ```\n */\n static validate<T extends object>(instance: T): Problem[] {\n if (!this.isEntity(instance)) {\n throw new Error('Cannot validate non-entity instance');\n }\n\n const problems: Problem[] = [];\n\n const keys = this.getPropertyKeys(instance);\n for (const key of keys) {\n const options = this.getPropertyOptions(instance, key);\n if (options) {\n const value = (instance as any)[key];\n if (value != null) {\n const validationProblems = this.runPropertyValidators(\n key,\n value,\n options,\n );\n problems.push(...validationProblems);\n }\n }\n }\n\n const entityValidators = this.getEntityValidators(instance);\n for (const validatorMethod of entityValidators) {\n const validatorProblems = (instance as any)[validatorMethod]();\n if (Array.isArray(validatorProblems)) {\n problems.push(...validatorProblems);\n }\n }\n\n return problems;\n }\n\n /**\n * Gets the validation problems for an entity instance\n *\n * @param instance - The entity instance\n * @returns Array of Problems (empty if no problems or instance not parsed)\n *\n * @remarks\n * - Only returns problems from the last parse() call\n * - Returns empty array if instance was not created via parse()\n * - Returns empty array if parse() was called with strict: true\n *\n * @example\n * ```typescript\n * const user = EntityUtils.parse(User, data);\n * const problems = EntityUtils.problems(user);\n * console.log(problems); // [Problem, ...]\n * ```\n */\n static problems<T extends object>(instance: T): Problem[] {\n return problemsStorage.get(instance) || [];\n }\n\n /**\n * Gets the raw input data that was used to create an entity instance\n *\n * @param instance - The entity instance\n * @returns The raw input object, or undefined if not available\n *\n * @remarks\n * - Only available for instances created via parse()\n * - Returns a reference to the original input data (not a copy)\n *\n * @example\n * ```typescript\n * const user = EntityUtils.parse(User, { name: 'John', age: 30 });\n * const rawInput = EntityUtils.getRawInput(user);\n * console.log(rawInput); // { name: 'John', age: 30 }\n * ```\n */\n static getRawInput<T extends object>(\n instance: T,\n ): Record<string, unknown> | undefined {\n return rawInputStorage.get(instance);\n }\n\n /**\n * Gets all entity validator method names for an entity\n * @private\n */\n private static getEntityValidators(target: object): string[] {\n let currentProto: any;\n\n if (target.constructor && target === target.constructor.prototype) {\n currentProto = target;\n } else {\n currentProto = Object.getPrototypeOf(target);\n }\n\n const validators: string[] = [];\n const seen = new Set<string>();\n\n while (currentProto && currentProto !== Object.prototype) {\n const protoValidators: string[] =\n Reflect.getOwnMetadata(ENTITY_VALIDATOR_METADATA_KEY, currentProto) ||\n [];\n\n for (const validator of protoValidators) {\n if (!seen.has(validator)) {\n seen.add(validator);\n validators.push(validator);\n }\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return validators;\n }\n}\n"],"names":["ENTITY_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","isEqualWith","ValidationError","Problem","prependPropertyPath","prependArrayIndex","createValidationError","combinePropertyPaths","isPrimitiveConstructor","deserializePrimitive","ok","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","sameEntity","a","b","getPropertyKeys","target","currentProto","prototype","keys","seen","Set","protoKeys","getOwnMetadata","key","has","add","push","getPropertyOptions","propertyKey","protoOptions","undefined","equals","val1","val2","diff","length","oldEntity","newEntity","Error","diffs","oldValue","newValue","propertyOptions","areEqual","property","changes","reduce","acc","toJSON","entity","result","value","options","serializeValue","passthrough","serialize","map","item","Date","toISOString","toString","parse","entityClass","plainObject","strict","data","hardProblems","message","isOptional","optional","deserializeValue","error","problems","instance","set","validate","typeConstructor","type","array","isSparse","sparse","arrayProblems","index","deserialize","deserializeSingleValue","validatePropertyValue","propertyPath","validators","validator","validatorProblems","problem","nestedProblems","prependedProblems","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","element","elementPath","elementProblems","validationProblems","entityValidators","getEntityValidators","validatorMethod","get","getRawInput","protoValidators"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/entity-utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n} from './types.js';\nimport { isEqualWith } from 'lodash-es';\nimport { ValidationError } from './validation-error.js';\nimport { Problem } from './problem.js';\nimport {\n prependPropertyPath,\n prependArrayIndex,\n createValidationError,\n combinePropertyPaths,\n} from './validation-utils.js';\nimport {\n isPrimitiveConstructor,\n deserializePrimitive,\n} from './primitive-deserializers.js';\nimport { ok } from 'assert';\n\n/**\n * WeakMap to store validation problems for entity instances\n */\nconst problemsStorage = new WeakMap<object, Problem[]>();\n\n/**\n * WeakMap to store raw input data for entity instances\n */\nconst rawInputStorage = new WeakMap<object, Record<string, unknown>>();\n\nexport class EntityUtils {\n /**\n * Checks if a given object is an instance of a class decorated with @Entity()\n * or if the provided value is an entity class itself\n *\n * @param obj - The object or class to check\n * @returns true if the object is an entity instance or entity class, false otherwise\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * name: string;\n * }\n *\n * const user = new User();\n * console.log(EntityUtils.isEntity(user)); // true\n * console.log(EntityUtils.isEntity(User)); // true\n * console.log(EntityUtils.isEntity({})); // false\n * ```\n */\n static isEntity(obj: unknown): obj is object {\n if (obj == null) {\n return false;\n }\n\n // Check if obj is a constructor function (class)\n if (typeof obj === 'function') {\n return Reflect.hasMetadata(ENTITY_METADATA_KEY, obj);\n }\n\n // Check if obj is an object instance\n if (typeof obj !== 'object' || Array.isArray(obj)) {\n return false;\n }\n\n const constructor = Object.getPrototypeOf(obj).constructor;\n return Reflect.hasMetadata(ENTITY_METADATA_KEY, constructor);\n }\n\n static sameEntity(a: object, b: object): boolean {\n if (!this.isEntity(a) || !this.isEntity(b)) {\n return false;\n }\n\n return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);\n }\n\n static getPropertyKeys(target: object): string[] {\n // Determine if we're dealing with a prototype or an instance\n let currentProto: any;\n\n // Check if target is a prototype by checking if it has a constructor property\n // and if target === target.constructor.prototype\n if (target.constructor && target === target.constructor.prototype) {\n // target is already a prototype\n currentProto = target;\n } else {\n // target is an instance, get its prototype\n currentProto = Object.getPrototypeOf(target);\n }\n\n const keys: string[] = [];\n const seen = new Set<string>();\n\n // Walk the prototype chain to collect all inherited properties\n while (currentProto && currentProto !== Object.prototype) {\n // Use getOwnMetadata to only get metadata directly on this prototype\n const protoKeys: string[] =\n Reflect.getOwnMetadata(PROPERTY_METADATA_KEY, currentProto) || [];\n\n for (const key of protoKeys) {\n if (!seen.has(key)) {\n seen.add(key);\n keys.push(key);\n }\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return keys;\n }\n\n static getPropertyOptions(\n target: object,\n propertyKey: string,\n ): PropertyOptions | undefined {\n // Determine if we're dealing with a prototype or an instance\n let currentProto: any;\n\n // Check if target is a prototype by checking if it has a constructor property\n // and if target === target.constructor.prototype\n if (target.constructor && target === target.constructor.prototype) {\n // target is already a prototype\n currentProto = target;\n } else {\n // target is an instance, get its prototype\n currentProto = Object.getPrototypeOf(target);\n }\n\n // Walk the prototype chain to find the property options\n while (currentProto && currentProto !== Object.prototype) {\n const protoOptions: Record<string, PropertyOptions> =\n Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, currentProto) ||\n {};\n\n if (protoOptions[propertyKey]) {\n return protoOptions[propertyKey];\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return undefined;\n }\n\n static equals(a: unknown, b: unknown): boolean {\n return isEqualWith(a, b, (val1, val2) => {\n if (this.isEntity(val1)) {\n if (!this.sameEntity(val1, val2)) {\n return false;\n }\n\n const diff = this.diff(val1, val2);\n\n return diff.length === 0;\n } else if (\n val1 != null &&\n val2 != null &&\n typeof val1 === 'object' &&\n !Array.isArray(val1) &&\n typeof val2 === 'object' &&\n !Array.isArray(val2) &&\n 'equals' in val1 &&\n typeof val1.equals === 'function'\n ) {\n return val1.equals(val2);\n }\n\n return undefined;\n });\n }\n\n static diff<T extends object>(\n oldEntity: T,\n newEntity: T,\n ): { property: string; oldValue: unknown; newValue: unknown }[] {\n if (!this.sameEntity(oldEntity, newEntity)) {\n throw new Error('Entities must be of the same type to compute diff');\n }\n\n const diffs: { property: string; oldValue: unknown; newValue: unknown }[] =\n [];\n\n const keys = this.getPropertyKeys(oldEntity);\n\n for (const key of keys) {\n const oldValue = (oldEntity as any)[key];\n const newValue = (newEntity as any)[key];\n\n // Check if there's a custom equals function for this property\n const propertyOptions = this.getPropertyOptions(oldEntity, key);\n\n let areEqual: boolean;\n if (oldValue == null && newValue == null) {\n areEqual = oldValue === newValue;\n } else if (oldValue == null || newValue == null) {\n areEqual = false;\n } else {\n areEqual = propertyOptions?.equals\n ? propertyOptions.equals(oldValue, newValue)\n : this.equals(oldValue, newValue);\n }\n\n if (!areEqual) {\n diffs.push({ property: key, oldValue, newValue });\n }\n }\n\n return diffs;\n }\n\n static changes<T extends object>(oldEntity: T, newEntity: T): Partial<T> {\n if (!this.sameEntity(oldEntity, newEntity)) {\n throw new Error('Entities must be of the same type to compute changes');\n }\n\n const diff = this.diff(oldEntity, newEntity);\n\n return diff.reduce((acc, { property, newValue }) => {\n (acc as any)[property] = newValue;\n return acc;\n }, {} as Partial<T>);\n }\n\n /**\n * Serializes an entity to a plain object, converting only properties decorated with @Property()\n *\n * @param entity - The entity instance to serialize\n * @returns A plain object containing only the serialized decorated properties\n *\n * @remarks\n * Serialization rules:\n * - Only properties decorated with @Property() are included\n * - If a property has a custom toJSON() method, it will be used\n * - Nested entities are recursively serialized using EntityUtils.toJSON()\n * - Arrays are mapped with toJSON() applied to each element\n * - Date objects are serialized to ISO strings\n * - bigint values are serialized to strings\n * - undefined values are excluded from the output\n * - null values are included in the output\n * - Circular references are not supported (will cause stack overflow)\n *\n * @example\n * ```typescript\n * @Entity()\n * class Address {\n * @Property() street: string;\n * @Property() city: string;\n * }\n *\n * @Entity()\n * class User {\n * @Property() name: string;\n * @Property() address: Address;\n * @Property() createdAt: Date;\n * undecorated: string; // Will not be serialized\n * }\n *\n * const user = new User();\n * user.name = 'John';\n * user.address = new Address();\n * user.address.street = '123 Main St';\n * user.address.city = 'Boston';\n * user.createdAt = new Date('2024-01-01');\n * user.undecorated = 'ignored';\n *\n * const json = EntityUtils.toJSON(user);\n * // {\n * // name: 'John',\n * // address: { street: '123 Main St', city: 'Boston' },\n * // createdAt: '2024-01-01T00:00:00.000Z'\n * // }\n * ```\n */\n static toJSON<T extends object>(entity: T): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const keys = this.getPropertyKeys(entity);\n\n for (const key of keys) {\n const value = (entity as any)[key];\n\n // Skip undefined values\n if (value === undefined) {\n continue;\n }\n\n const options = this.getPropertyOptions(entity, key);\n result[key] = this.serializeValue(value, options);\n }\n\n return result;\n }\n\n /**\n * Serializes a single value according to the toJSON rules\n * @private\n */\n private static serializeValue(\n value: unknown,\n options?: PropertyOptions,\n ): unknown {\n if (value === null) {\n return null;\n }\n\n if (value === undefined) {\n return undefined;\n }\n\n const passthrough = options?.passthrough === true;\n if (passthrough) {\n return value;\n }\n\n if (Array.isArray(value)) {\n if (options?.serialize) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return value.map((item) => options.serialize!(item as any));\n }\n return value.map((item) => this.serializeValue(item));\n }\n\n if (options?.serialize) {\n return options.serialize(value as any);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (this.isEntity(value)) {\n return this.toJSON(value);\n }\n\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n\n throw new Error(\n `Cannot serialize value of type '${typeof value}'. Use passthrough: true in @Property() to explicitly allow serialization of unknown types.`,\n );\n }\n\n /**\n * Deserializes a plain object to an entity instance\n *\n * @param entityClass - The entity class constructor. Must accept a data object parameter.\n * @param plainObject - The plain object to deserialize\n * @param options - Parse options (strict mode)\n * @returns Promise resolving to a new instance of the entity with deserialized values\n *\n * @remarks\n * Deserialization rules:\n * - All @Property() decorators must include type metadata for parse() to work\n * - Properties without type metadata will throw an error\n * - Required properties (optional !== true) must be present and not null/undefined\n * - Optional properties (optional === true) can be undefined or null\n * - Arrays are supported with the array: true option\n * - Nested entities are recursively deserialized\n * - Type conversion is strict (no coercion)\n * - Entity constructors must accept a required data parameter\n *\n * Validation behavior:\n * - If strict: true - both HARD and SOFT problems throw ValidationError\n * - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored\n * - Property validators run first, then entity validators\n * - Validators can be synchronous or asynchronous\n * - Problems are accessible via EntityUtils.problems()\n * - Raw input data is accessible via EntityUtils.getRawInput()\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n * @Property({ type: () => Number }) age!: number;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const json = { name: 'John', age: 30 };\n * const user = await EntityUtils.parse(User, json);\n * const userStrict = await EntityUtils.parse(User, json, { strict: true });\n * ```\n */\n static async parse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n options?: { strict?: boolean },\n ): Promise<T> {\n if (plainObject == null) {\n throw createValidationError(\n `Expects an object but received ${typeof plainObject}`,\n );\n }\n if (Array.isArray(plainObject)) {\n throw createValidationError(`Expects an object but received array`);\n }\n if (typeof plainObject !== 'object') {\n throw createValidationError(\n `Expects an object but received ${typeof plainObject}`,\n );\n }\n\n const strict = options?.strict ?? false;\n const keys = this.getPropertyKeys(entityClass.prototype);\n const data: Record<string, unknown> = {};\n const hardProblems: Problem[] = [];\n\n for (const key of keys) {\n const propertyOptions = this.getPropertyOptions(\n entityClass.prototype,\n key,\n );\n\n if (!propertyOptions) {\n hardProblems.push(\n new Problem({\n property: key,\n message: `Property has no metadata. This should not happen if @Property() was used correctly.`,\n }),\n );\n continue;\n }\n\n const value = (plainObject as Record<string, unknown>)[key];\n\n if (propertyOptions.passthrough === true) {\n data[key] = value;\n continue;\n }\n\n const isOptional = propertyOptions.optional === true;\n\n if (!(key in plainObject)) {\n if (!isOptional) {\n hardProblems.push(\n new Problem({\n property: key,\n message: 'Required property is missing from input',\n }),\n );\n }\n continue;\n }\n\n if (value === null || value === undefined) {\n if (!isOptional) {\n hardProblems.push(\n new Problem({\n property: key,\n message: 'Cannot be null or undefined',\n }),\n );\n }\n data[key] = value;\n continue;\n }\n\n try {\n data[key] = await this.deserializeValue(value, propertyOptions);\n } catch (error) {\n if (error instanceof ValidationError) {\n const problems = prependPropertyPath(key, error);\n hardProblems.push(...problems);\n } else if (error instanceof Error) {\n hardProblems.push(\n new Problem({\n property: key,\n message: error.message,\n }),\n );\n } else {\n throw error;\n }\n }\n }\n\n if (hardProblems.length > 0) {\n throw new ValidationError(hardProblems);\n }\n\n const instance = new entityClass(data);\n\n rawInputStorage.set(instance, plainObject as Record<string, unknown>);\n\n const problems = await this.validate(instance);\n\n if (problems.length > 0) {\n if (strict) {\n throw new ValidationError(problems);\n } else {\n problemsStorage.set(instance, problems);\n }\n }\n\n return instance;\n }\n\n /**\n * Deserializes a single value according to the type metadata\n * @private\n */\n private static async deserializeValue(\n value: unknown,\n options: PropertyOptions,\n ): Promise<unknown> {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\n const isArray = options.array === true;\n const isSparse = options.sparse === true;\n\n if (isArray) {\n if (!Array.isArray(value)) {\n throw createValidationError(\n `Expects an array but received ${typeof value}`,\n );\n }\n\n const arrayProblems: Problem[] = [];\n const result: unknown[] = [];\n\n for (let index = 0; index < value.length; index++) {\n const item = value[index];\n if (item === null || item === undefined) {\n if (!isSparse) {\n arrayProblems.push(\n new Problem({\n property: `[${index}]`,\n message: 'Cannot be null or undefined.',\n }),\n );\n }\n result.push(item);\n } else {\n try {\n if (options.deserialize) {\n result.push(options.deserialize(item));\n } else {\n result.push(\n await this.deserializeSingleValue(item, typeConstructor),\n );\n }\n } catch (error) {\n if (error instanceof ValidationError) {\n const problems = prependArrayIndex(index, error);\n arrayProblems.push(...problems);\n } else {\n throw error;\n }\n }\n }\n }\n\n if (arrayProblems.length > 0) {\n throw new ValidationError(arrayProblems);\n }\n\n return result;\n }\n\n if (options.deserialize) {\n return options.deserialize(value);\n }\n\n return await this.deserializeSingleValue(value, typeConstructor);\n }\n\n /**\n * Deserializes a single non-array value\n * Reports validation errors with empty property (caller will prepend context)\n * @private\n */\n private static async deserializeSingleValue(\n value: unknown,\n typeConstructor: any,\n ): Promise<unknown> {\n if (isPrimitiveConstructor(typeConstructor)) {\n return deserializePrimitive(value, typeConstructor);\n }\n\n if (this.isEntity(typeConstructor)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw createValidationError(\n `Expects an object but received ${typeof value}`,\n );\n }\n\n return await this.parse(\n typeConstructor as new (data: any) => object,\n value as Record<string, unknown>,\n );\n }\n\n throw createValidationError(\n `Has unknown type constructor. Supported types are: String, Number, Boolean, Date, BigInt, and @Entity() classes. Use passthrough: true to explicitly allow unknown types.`,\n );\n }\n\n /**\n * Validates a property value by running validators and nested entity validation.\n * Prepends the property path to all returned problems.\n * @private\n */\n private static async validatePropertyValue(\n propertyPath: string,\n value: unknown,\n validators: PropertyOptions['validators'],\n ): Promise<Problem[]> {\n const problems: Problem[] = [];\n\n if (validators) {\n for (const validator of validators) {\n const validatorProblems = await validator({ value });\n // Prepend propertyPath to all problems\n for (const problem of validatorProblems) {\n problems.push(\n new Problem({\n property: combinePropertyPaths(propertyPath, problem.property),\n message: problem.message,\n }),\n );\n }\n }\n }\n\n if (EntityUtils.isEntity(value)) {\n const nestedProblems = await EntityUtils.validate(value);\n const prependedProblems = prependPropertyPath(\n propertyPath,\n new ValidationError(nestedProblems),\n );\n problems.push(...prependedProblems);\n }\n\n return problems;\n }\n\n /**\n * Runs property validators for a given property value\n * @private\n */\n private static async runPropertyValidators(\n key: string,\n value: unknown,\n options: PropertyOptions,\n ): Promise<Problem[]> {\n const problems: Problem[] = [];\n const isArray = options?.array === true;\n const isPassthrough = options?.passthrough === true;\n\n if (isPassthrough || !isArray) {\n const valueProblems = await this.validatePropertyValue(\n key,\n value,\n options.validators,\n );\n problems.push(...valueProblems);\n } else {\n ok(Array.isArray(value), 'Value must be an array for array property');\n\n const arrayValidators = options.arrayValidators || [];\n for (const validator of arrayValidators) {\n const validatorProblems = await validator({ value });\n for (const problem of validatorProblems) {\n problems.push(\n new Problem({\n property: combinePropertyPaths(key, problem.property),\n message: problem.message,\n }),\n );\n }\n }\n\n const validators = options.validators || [];\n if (validators.length > 0) {\n for (let i = 0; i < value.length; i++) {\n const element = value[i];\n if (element !== null && element !== undefined) {\n const elementPath = `${key}[${i}]`;\n const elementProblems = await this.validatePropertyValue(\n elementPath,\n element,\n validators,\n );\n problems.push(...elementProblems);\n }\n }\n }\n }\n\n return problems;\n }\n\n /**\n * Validates an entity instance by running all property and entity validators\n *\n * @param instance - The entity instance to validate\n * @returns Promise resolving to array of Problems found during validation (empty if valid)\n *\n * @remarks\n * - Property validators run first, then entity validators\n * - Each validator can be synchronous or asynchronous\n * - Empty array means no problems found\n *\n * @example\n * ```typescript\n * const user = new User({ name: '', age: -5 });\n * const problems = await EntityUtils.validate(user);\n * console.log(problems); // [Problem, Problem, ...]\n * ```\n */\n static async validate<T extends object>(instance: T): Promise<Problem[]> {\n if (!this.isEntity(instance)) {\n throw new Error('Cannot validate non-entity instance');\n }\n\n const problems: Problem[] = [];\n\n const keys = this.getPropertyKeys(instance);\n for (const key of keys) {\n const options = this.getPropertyOptions(instance, key);\n if (options) {\n const value = (instance as any)[key];\n if (value != null) {\n const validationProblems = await this.runPropertyValidators(\n key,\n value,\n options,\n );\n problems.push(...validationProblems);\n }\n }\n }\n\n const entityValidators = this.getEntityValidators(instance);\n for (const validatorMethod of entityValidators) {\n const validatorProblems = await (instance as any)[validatorMethod]();\n if (Array.isArray(validatorProblems)) {\n problems.push(...validatorProblems);\n }\n }\n\n return problems;\n }\n\n /**\n * Gets the validation problems for an entity instance\n *\n * @param instance - The entity instance\n * @returns Array of Problems (empty if no problems or instance not parsed)\n *\n * @remarks\n * - Only returns problems from the last parse() call\n * - Returns empty array if instance was not created via parse()\n * - Returns empty array if parse() was called with strict: true\n *\n * @example\n * ```typescript\n * const user = EntityUtils.parse(User, data);\n * const problems = EntityUtils.problems(user);\n * console.log(problems); // [Problem, ...]\n * ```\n */\n static problems<T extends object>(instance: T): Problem[] {\n return problemsStorage.get(instance) || [];\n }\n\n /**\n * Gets the raw input data that was used to create an entity instance\n *\n * @param instance - The entity instance\n * @returns The raw input object, or undefined if not available\n *\n * @remarks\n * - Only available for instances created via parse()\n * - Returns a reference to the original input data (not a copy)\n *\n * @example\n * ```typescript\n * const user = EntityUtils.parse(User, { name: 'John', age: 30 });\n * const rawInput = EntityUtils.getRawInput(user);\n * console.log(rawInput); // { name: 'John', age: 30 }\n * ```\n */\n static getRawInput<T extends object>(\n instance: T,\n ): Record<string, unknown> | undefined {\n return rawInputStorage.get(instance);\n }\n\n /**\n * Gets all entity validator method names for an entity\n * @private\n */\n private static getEntityValidators(target: object): string[] {\n let currentProto: any;\n\n if (target.constructor && target === target.constructor.prototype) {\n currentProto = target;\n } else {\n currentProto = Object.getPrototypeOf(target);\n }\n\n const validators: string[] = [];\n const seen = new Set<string>();\n\n while (currentProto && currentProto !== Object.prototype) {\n const protoValidators: string[] =\n Reflect.getOwnMetadata(ENTITY_VALIDATOR_METADATA_KEY, currentProto) ||\n [];\n\n for (const validator of protoValidators) {\n if (!seen.has(validator)) {\n seen.add(validator);\n validators.push(validator);\n }\n }\n\n currentProto = Object.getPrototypeOf(currentProto);\n }\n\n return validators;\n }\n}\n"],"names":["ENTITY_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","isEqualWith","ValidationError","Problem","prependPropertyPath","prependArrayIndex","createValidationError","combinePropertyPaths","isPrimitiveConstructor","deserializePrimitive","ok","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","sameEntity","a","b","getPropertyKeys","target","currentProto","prototype","keys","seen","Set","protoKeys","getOwnMetadata","key","has","add","push","getPropertyOptions","propertyKey","protoOptions","undefined","equals","val1","val2","diff","length","oldEntity","newEntity","Error","diffs","oldValue","newValue","propertyOptions","areEqual","property","changes","reduce","acc","toJSON","entity","result","value","options","serializeValue","passthrough","serialize","map","item","Date","toISOString","toString","parse","entityClass","plainObject","strict","data","hardProblems","message","isOptional","optional","deserializeValue","error","problems","instance","set","validate","typeConstructor","type","array","isSparse","sparse","arrayProblems","index","deserialize","deserializeSingleValue","validatePropertyValue","propertyPath","validators","validator","validatorProblems","problem","nestedProblems","prependedProblems","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","element","elementPath","elementProblems","validationProblems","entityValidators","getEntityValidators","validatorMethod","get","getRawInput","protoValidators"],"mappings":"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"}
|
package/dist/lib/problem.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
/**
|
|
3
|
-
* Represents a SOFT validation problem
|
|
4
|
-
*/
|
|
5
2
|
export declare class Problem {
|
|
6
3
|
readonly property: string;
|
|
7
4
|
readonly message: string;
|
|
8
5
|
constructor(data: {
|
|
9
|
-
property
|
|
6
|
+
property?: string;
|
|
10
7
|
message: string;
|
|
11
8
|
});
|
|
12
9
|
toString(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"problem.d.ts","sourceRoot":"","sources":["../../src/lib/problem.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAI1B
|
|
1
|
+
{"version":3,"file":"problem.d.ts","sourceRoot":"","sources":["../../src/lib/problem.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAI1B,qBACa,OAAO;IAElB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAG1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAKxD,QAAQ,IAAI,MAAM;CAGnB"}
|
package/dist/lib/problem.js
CHANGED
package/dist/lib/problem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/problem.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { Entity } from './entity.js';\nimport { StringProperty } from './property.js';\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/lib/problem.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { Entity } from './entity.js';\nimport { StringProperty } from './property.js';\n\n@Entity()\nexport class Problem {\n @StringProperty()\n readonly property: string;\n\n @StringProperty()\n readonly message: string;\n\n constructor(data: { property?: string; message: string }) {\n this.property = data.property ?? '';\n this.message = data.message;\n }\n\n toString(): string {\n return `${this.property}: ${this.message}`;\n }\n}\n"],"names":["Entity","StringProperty","Problem","data","property","message","toString"],"mappings":";;AAAA,OAAO,mBAAmB;AAC1B,SAASA,MAAM,QAAQ,cAAc;AACrC,SAASC,cAAc,QAAQ,gBAAgB;AAG/C,OAAO,MAAMC;IAOX,YAAYC,IAA4C,CAAE;QACxD,IAAI,CAACC,QAAQ,GAAGD,KAAKC,QAAQ,IAAI;QACjC,IAAI,CAACC,OAAO,GAAGF,KAAKE,OAAO;IAC7B;IAEAC,WAAmB;QACjB,OAAO,GAAG,IAAI,CAACF,QAAQ,CAAC,EAAE,EAAE,IAAI,CAACC,OAAO,EAAE;IAC5C;AACF"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -151,34 +151,36 @@ export interface PropertyOptions<T = any, C extends CtorLike<T> = AnyCtor<T> | B
|
|
|
151
151
|
/**
|
|
152
152
|
* A validator function for a property.
|
|
153
153
|
* The validator receives the value and returns Problems with property paths relative to the value.
|
|
154
|
+
* Can be synchronous or asynchronous.
|
|
154
155
|
* The calling code will prepend the actual property key to all returned problems.
|
|
155
156
|
*
|
|
156
157
|
* @param data - Object containing the value to validate
|
|
157
158
|
* @param data.value - The value to validate
|
|
158
|
-
* @returns Array of Problems (empty if valid)
|
|
159
|
+
* @returns Array of Problems (empty if valid) or Promise resolving to Problems.
|
|
160
|
+
* Problems should have empty property for the value itself,
|
|
159
161
|
* or relative paths for nested properties (e.g., 'name', '[0]', 'address.street')
|
|
160
162
|
*
|
|
161
163
|
* @example
|
|
162
164
|
* ```typescript
|
|
163
|
-
* //
|
|
165
|
+
* // Synchronous validator
|
|
164
166
|
* (({ value }) =>
|
|
165
167
|
* value.length < 3 ? [new Problem({ property: '', message: 'Too short' })] : [])
|
|
166
168
|
*
|
|
167
|
-
* //
|
|
168
|
-
* (
|
|
169
|
-
* const
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* })
|
|
169
|
+
* // Asynchronous validator
|
|
170
|
+
* async ({ value }) => {
|
|
171
|
+
* const exists = await checkDatabase(value);
|
|
172
|
+
* return exists ? [] : [new Problem({ property: '', message: 'Not found' })];
|
|
173
|
+
* }
|
|
173
174
|
* ```
|
|
174
175
|
*/
|
|
175
176
|
export type PropertyValidator<T> = (data: {
|
|
176
177
|
value: T;
|
|
177
|
-
}) => Problem[]
|
|
178
|
+
}) => Problem[] | Promise<Problem[]>;
|
|
178
179
|
/**
|
|
179
|
-
* A validator function for an entity
|
|
180
|
+
* A validator function for an entity.
|
|
181
|
+
* Can be synchronous or asynchronous.
|
|
180
182
|
* @param instance - The entity instance to validate
|
|
181
|
-
* @returns Array of Problems (empty if valid)
|
|
183
|
+
* @returns Array of Problems (empty if valid) or Promise resolving to Problems
|
|
182
184
|
*/
|
|
183
|
-
export type EntityValidatorFn<T = any> = (instance: T) => Problem[]
|
|
185
|
+
export type EntityValidatorFn<T = any> = (instance: T) => Problem[] | Promise<Problem[]>;
|
|
184
186
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,qBAAqB,eAA8B,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAA4B,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAGF,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,GAAG;IAAE,SAAS,EAAE,CAAC,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,CAAC;AAEpB,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;AAEpD,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,iBAAiB,GAC3D,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,kBAAkB,GAC1B,OAAO,GACP,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,eAAe,GACvB,IAAI,GACJ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,CAAC,GACD,KAAK,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,eAAe,CAC9B,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY;IAEjD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAEzE;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC,CAAC;IAEd;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAEtD;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAE7D;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAExD;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;CAChE;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,qBAAqB,eAA8B,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAA4B,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAGF,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,GAAG;IAAE,SAAS,EAAE,CAAC,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,CAAC;AAEpB,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;AAEpD,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,iBAAiB,GAC3D,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,kBAAkB,GAC1B,OAAO,GACP,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,eAAe,GACvB,IAAI,GACJ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,CAAC,GACD,KAAK,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,eAAe,CAC9B,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY;IAEjD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAEzE;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC,CAAC;IAEd;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAEtD;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAE7D;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAExD;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;CAChE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE;IACxC,KAAK,EAAE,CAAC,CAAC;CACV,KAAK,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAErC;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,GAAG,IAAI,CACvC,QAAQ,EAAE,CAAC,KACR,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC"}
|
package/dist/lib/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-wrapper-object-types */\nimport type { Problem } from './problem.js';\n\n/**\n * Metadata key used to store property information\n */\nexport const PROPERTY_METADATA_KEY = Symbol('property:metadata');\n\n/**\n * Metadata key used to store property options\n */\nexport const PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'property:options:metadata',\n);\n\n/**\n * Metadata key used to store entity information\n */\nexport const ENTITY_METADATA_KEY = Symbol('entity:metadata');\n\n/**\n * Metadata key used to store entity validator methods\n */\nexport const ENTITY_VALIDATOR_METADATA_KEY = Symbol(\n 'entity:validator:metadata',\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport type AnyCtor<T = any> = Function & { prototype: T };\n\nexport type BuiltinCtors =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | SymbolConstructor\n | DateConstructor;\n\n/**\n * Type constructors for primitive types that can be deserialized\n * (excludes Symbol which cannot be deserialized from JSON)\n */\nexport type PrimitiveConstructor =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | DateConstructor;\n\nexport type CtorLike<T> = AnyCtor<T> | BuiltinCtors;\n\nexport type InstanceOfCtorLike<C> = C extends StringConstructor\n ? string\n : C extends NumberConstructor\n ? number\n : C extends BooleanConstructor\n ? boolean\n : C extends BigIntConstructor\n ? bigint\n : C extends SymbolConstructor\n ? symbol\n : C extends DateConstructor\n ? Date\n : C extends AnyCtor<infer T>\n ? T\n : never;\n\n/**\n * Options for the Property decorator\n */\nexport interface PropertyOptions<\n T = any,\n C extends CtorLike<T> = AnyCtor<T> | BuiltinCtors,\n> {\n /**\n * Custom equality comparison function for this property\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns true if values are equal, false otherwise\n */\n equals?: (a: InstanceOfCtorLike<C>, b: InstanceOfCtorLike<C>) => boolean;\n\n /**\n * Type constructor for this property. Required for EntityUtils.parse() support.\n * Use a function that returns the type constructor to support forward references.\n * @example\n * @Property({ type: () => String })\n * name!: string;\n *\n * @Property({ type: () => Address })\n * address!: Address;\n */\n type: () => C;\n\n /**\n * Whether this property is an array. Defaults to false.\n * When true, the deserializer will map over array elements.\n * @example\n * @Property({ type: () => String, array: true })\n * tags!: string[];\n */\n array?: boolean;\n\n /**\n * Whether this property is optional. Defaults to false.\n * When true, the property can be undefined or null.\n * When false, the property must be present and not null/undefined.\n * @example\n * @Property({ type: () => String, optional: true })\n * nickname?: string;\n */\n optional?: boolean;\n\n /**\n * Whether the array can contain null/undefined elements. Defaults to false.\n * Only applicable when array is true.\n * When false (default), null/undefined elements will cause an error.\n * When true, null/undefined elements are allowed in the array.\n * @example\n * @Property({ type: () => String, array: true, sparse: true })\n * tags!: (string | null)[];\n */\n sparse?: boolean;\n\n /**\n * Whether to bypass type validation and pass values through as-is.\n * Use this for generic types like Record<string, unknown> or any.\n * When true, no type checking or transformation is performed.\n * Also bypasses any custom serialize/deserialize callbacks.\n * @example\n * @Property({ passthrough: true })\n * metadata!: Record<string, unknown>;\n */\n passthrough?: boolean;\n\n /**\n * Custom serialization function to convert the property value to JSON-compatible format.\n * Must be paired with deserialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n serialize?: (value: InstanceOfCtorLike<C>) => unknown;\n\n /**\n * Custom deserialization function to convert JSON data back to the property type.\n * Must be paired with serialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n deserialize?: (serialized: unknown) => InstanceOfCtorLike<C>;\n\n /**\n * Array of validator functions for this property.\n * Each validator receives the property value and validation context.\n * Empty array means validation passed.\n * If the property is an array (array: true), these validators will run against each item.\n * Use arrayValidators instead to validate the array as a whole.\n * If passthrough is true, validators will run against the raw value.\n * @example\n * @Property({\n * type: () => String,\n * validators: [\n * (value, { createProblem }) =>\n * value.length > 10 ? [createProblem('Too long')] : []\n * ]\n * })\n * name!: string;\n */\n validators?: PropertyValidator<InstanceOfCtorLike<C>>[];\n\n /**\n * Array of validator functions for this property when it is an array.\n * Each validator receives the array value and validation context.\n * Empty array means validation passed.\n * Only applicable when array is true.\n * Not applicable when passthrough is true.\n * @example\n * @Property({\n * type: () => Number,\n * array: true,\n * arrayValidators: [\n * (value, { createProblem }) =>\n * value.length === 0 ? [createProblem('Array cannot be empty')] : []\n * ]\n * })\n * scores!: number[];\n */\n arrayValidators?: PropertyValidator<InstanceOfCtorLike<C>[]>[];\n}\n\n/**\n * A validator function for a property.\n * The validator receives the value and returns Problems with property paths relative to the value.\n * The calling code will prepend the actual property key to all returned problems.\n *\n * @param data - Object containing the value to validate\n * @param data.value - The value to validate\n * @returns Array of Problems (empty if valid)
|
|
1
|
+
{"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-wrapper-object-types */\nimport type { Problem } from './problem.js';\n\n/**\n * Metadata key used to store property information\n */\nexport const PROPERTY_METADATA_KEY = Symbol('property:metadata');\n\n/**\n * Metadata key used to store property options\n */\nexport const PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'property:options:metadata',\n);\n\n/**\n * Metadata key used to store entity information\n */\nexport const ENTITY_METADATA_KEY = Symbol('entity:metadata');\n\n/**\n * Metadata key used to store entity validator methods\n */\nexport const ENTITY_VALIDATOR_METADATA_KEY = Symbol(\n 'entity:validator:metadata',\n);\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport type AnyCtor<T = any> = Function & { prototype: T };\n\nexport type BuiltinCtors =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | SymbolConstructor\n | DateConstructor;\n\n/**\n * Type constructors for primitive types that can be deserialized\n * (excludes Symbol which cannot be deserialized from JSON)\n */\nexport type PrimitiveConstructor =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | DateConstructor;\n\nexport type CtorLike<T> = AnyCtor<T> | BuiltinCtors;\n\nexport type InstanceOfCtorLike<C> = C extends StringConstructor\n ? string\n : C extends NumberConstructor\n ? number\n : C extends BooleanConstructor\n ? boolean\n : C extends BigIntConstructor\n ? bigint\n : C extends SymbolConstructor\n ? symbol\n : C extends DateConstructor\n ? Date\n : C extends AnyCtor<infer T>\n ? T\n : never;\n\n/**\n * Options for the Property decorator\n */\nexport interface PropertyOptions<\n T = any,\n C extends CtorLike<T> = AnyCtor<T> | BuiltinCtors,\n> {\n /**\n * Custom equality comparison function for this property\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns true if values are equal, false otherwise\n */\n equals?: (a: InstanceOfCtorLike<C>, b: InstanceOfCtorLike<C>) => boolean;\n\n /**\n * Type constructor for this property. Required for EntityUtils.parse() support.\n * Use a function that returns the type constructor to support forward references.\n * @example\n * @Property({ type: () => String })\n * name!: string;\n *\n * @Property({ type: () => Address })\n * address!: Address;\n */\n type: () => C;\n\n /**\n * Whether this property is an array. Defaults to false.\n * When true, the deserializer will map over array elements.\n * @example\n * @Property({ type: () => String, array: true })\n * tags!: string[];\n */\n array?: boolean;\n\n /**\n * Whether this property is optional. Defaults to false.\n * When true, the property can be undefined or null.\n * When false, the property must be present and not null/undefined.\n * @example\n * @Property({ type: () => String, optional: true })\n * nickname?: string;\n */\n optional?: boolean;\n\n /**\n * Whether the array can contain null/undefined elements. Defaults to false.\n * Only applicable when array is true.\n * When false (default), null/undefined elements will cause an error.\n * When true, null/undefined elements are allowed in the array.\n * @example\n * @Property({ type: () => String, array: true, sparse: true })\n * tags!: (string | null)[];\n */\n sparse?: boolean;\n\n /**\n * Whether to bypass type validation and pass values through as-is.\n * Use this for generic types like Record<string, unknown> or any.\n * When true, no type checking or transformation is performed.\n * Also bypasses any custom serialize/deserialize callbacks.\n * @example\n * @Property({ passthrough: true })\n * metadata!: Record<string, unknown>;\n */\n passthrough?: boolean;\n\n /**\n * Custom serialization function to convert the property value to JSON-compatible format.\n * Must be paired with deserialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n serialize?: (value: InstanceOfCtorLike<C>) => unknown;\n\n /**\n * Custom deserialization function to convert JSON data back to the property type.\n * Must be paired with serialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n deserialize?: (serialized: unknown) => InstanceOfCtorLike<C>;\n\n /**\n * Array of validator functions for this property.\n * Each validator receives the property value and validation context.\n * Empty array means validation passed.\n * If the property is an array (array: true), these validators will run against each item.\n * Use arrayValidators instead to validate the array as a whole.\n * If passthrough is true, validators will run against the raw value.\n * @example\n * @Property({\n * type: () => String,\n * validators: [\n * (value, { createProblem }) =>\n * value.length > 10 ? [createProblem('Too long')] : []\n * ]\n * })\n * name!: string;\n */\n validators?: PropertyValidator<InstanceOfCtorLike<C>>[];\n\n /**\n * Array of validator functions for this property when it is an array.\n * Each validator receives the array value and validation context.\n * Empty array means validation passed.\n * Only applicable when array is true.\n * Not applicable when passthrough is true.\n * @example\n * @Property({\n * type: () => Number,\n * array: true,\n * arrayValidators: [\n * (value, { createProblem }) =>\n * value.length === 0 ? [createProblem('Array cannot be empty')] : []\n * ]\n * })\n * scores!: number[];\n */\n arrayValidators?: PropertyValidator<InstanceOfCtorLike<C>[]>[];\n}\n\n/**\n * A validator function for a property.\n * The validator receives the value and returns Problems with property paths relative to the value.\n * Can be synchronous or asynchronous.\n * The calling code will prepend the actual property key to all returned problems.\n *\n * @param data - Object containing the value to validate\n * @param data.value - The value to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems.\n * Problems should have empty property for the value itself,\n * or relative paths for nested properties (e.g., 'name', '[0]', 'address.street')\n *\n * @example\n * ```typescript\n * // Synchronous validator\n * (({ value }) =>\n * value.length < 3 ? [new Problem({ property: '', message: 'Too short' })] : [])\n *\n * // Asynchronous validator\n * async ({ value }) => {\n * const exists = await checkDatabase(value);\n * return exists ? [] : [new Problem({ property: '', message: 'Not found' })];\n * }\n * ```\n */\nexport type PropertyValidator<T> = (data: {\n value: T;\n}) => Problem[] | Promise<Problem[]>;\n\n/**\n * A validator function for an entity.\n * Can be synchronous or asynchronous.\n * @param instance - The entity instance to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems\n */\nexport type EntityValidatorFn<T = any> = (\n instance: T,\n) => Problem[] | Promise<Problem[]>;\n"],"names":["PROPERTY_METADATA_KEY","Symbol","PROPERTY_OPTIONS_METADATA_KEY","ENTITY_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY"],"mappings":"AAAA,qDAAqD,GACrD,6DAA6D,GAG7D;;CAEC,GACD,OAAO,MAAMA,wBAAwBC,OAAO,qBAAqB;AAEjE;;CAEC,GACD,OAAO,MAAMC,gCAAgCD,OAC3C,6BACA;AAEF;;CAEC,GACD,OAAO,MAAME,sBAAsBF,OAAO,mBAAmB;AAE7D;;CAEC,GACD,OAAO,MAAMG,gCAAgCH,OAC3C,6BACA"}
|