@rtpaulino/entity 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -127,6 +127,11 @@ export declare class EntityUtils {
|
|
|
127
127
|
* @private
|
|
128
128
|
*/
|
|
129
129
|
private static serializeValue;
|
|
130
|
+
/**
|
|
131
|
+
* Internal parse implementation with extended options
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
private static _parseInternal;
|
|
130
135
|
/**
|
|
131
136
|
* Deserializes a plain object to an entity instance
|
|
132
137
|
*
|
|
@@ -211,6 +216,87 @@ export declare class EntityUtils {
|
|
|
211
216
|
* ```
|
|
212
217
|
*/
|
|
213
218
|
static safeParse<T extends object>(entityClass: new (data: any) => T, plainObject: unknown, parseOptions?: ParseOptions): SafeOperationResult<T>;
|
|
219
|
+
/**
|
|
220
|
+
* Partially deserializes a plain object, returning a plain object with only present properties
|
|
221
|
+
*
|
|
222
|
+
* @param entityClass - The entity class constructor
|
|
223
|
+
* @param plainObject - The plain object to deserialize
|
|
224
|
+
* @param options - Options with strict mode
|
|
225
|
+
* @returns Promise resolving to a plain object with deserialized properties (Partial<T>)
|
|
226
|
+
*
|
|
227
|
+
* @remarks
|
|
228
|
+
* Differences from parse():
|
|
229
|
+
* - Returns a plain object, not an entity instance
|
|
230
|
+
* - Ignores missing properties (does not include them in result)
|
|
231
|
+
* - Does NOT apply default values to missing properties
|
|
232
|
+
* - When strict: false (default), properties with HARD problems are excluded from result but problems are tracked
|
|
233
|
+
* - When strict: true, any HARD problem throws ValidationError
|
|
234
|
+
* - Nested entities/arrays are still fully deserialized and validated as normal
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* @Entity()
|
|
239
|
+
* class User {
|
|
240
|
+
* @Property({ type: () => String }) name!: string;
|
|
241
|
+
* @Property({ type: () => Number, default: 0 }) age!: number;
|
|
242
|
+
*
|
|
243
|
+
* constructor(data: Partial<User>) {
|
|
244
|
+
* Object.assign(this, data);
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
247
|
+
*
|
|
248
|
+
* const partial = await EntityUtils.partialParse(User, { name: 'John' });
|
|
249
|
+
* // partial = { name: 'John' } (age is not included, default not applied)
|
|
250
|
+
*
|
|
251
|
+
* const partialWithError = await EntityUtils.partialParse(User, { name: 'John', age: 'invalid' });
|
|
252
|
+
* // partialWithError = { name: 'John' } (age excluded due to HARD problem)
|
|
253
|
+
* // Access problems via second return value
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
static partialParse<T extends object>(entityClass: new (data: any) => T, plainObject: unknown, options?: {
|
|
257
|
+
strict?: boolean;
|
|
258
|
+
}): Promise<Partial<T>>;
|
|
259
|
+
/**
|
|
260
|
+
* Safely performs partial deserialization without throwing errors
|
|
261
|
+
*
|
|
262
|
+
* @param entityClass - The entity class constructor
|
|
263
|
+
* @param plainObject - The plain object to deserialize
|
|
264
|
+
* @param options - Options with strict mode
|
|
265
|
+
* @returns Promise resolving to a result object with success flag, partial data, and problems
|
|
266
|
+
*
|
|
267
|
+
* @remarks
|
|
268
|
+
* Similar to partialParse() but returns a result object instead of throwing errors:
|
|
269
|
+
* - On success with strict: true - returns { success: true, data: Partial<T>, problems: [] }
|
|
270
|
+
* - On success with strict: false - returns { success: true, data: Partial<T>, problems: [...] } (includes hard problems for excluded properties)
|
|
271
|
+
* - On failure (strict mode only) - returns { success: false, data: undefined, problems: [...] }
|
|
272
|
+
*
|
|
273
|
+
* All partial deserialization rules from partialParse() apply.
|
|
274
|
+
* See partialParse() documentation for detailed behavior.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```typescript
|
|
278
|
+
* @Entity()
|
|
279
|
+
* class User {
|
|
280
|
+
* @Property({ type: () => String }) name!: string;
|
|
281
|
+
* @Property({ type: () => Number }) age!: number;
|
|
282
|
+
*
|
|
283
|
+
* constructor(data: Partial<User>) {
|
|
284
|
+
* Object.assign(this, data);
|
|
285
|
+
* }
|
|
286
|
+
* }
|
|
287
|
+
*
|
|
288
|
+
* const result = await EntityUtils.safePartialParse(User, { name: 'John', age: 'invalid' });
|
|
289
|
+
* if (result.success) {
|
|
290
|
+
* console.log(result.data); // { name: 'John' }
|
|
291
|
+
* console.log(result.problems); // [Problem for age property]
|
|
292
|
+
* } else {
|
|
293
|
+
* console.log(result.problems); // Hard problems (only in strict mode)
|
|
294
|
+
* }
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
static safePartialParse<T extends object>(entityClass: new (data: any) => T, plainObject: unknown, options?: {
|
|
298
|
+
strict?: boolean;
|
|
299
|
+
}): Promise<SafeOperationResult<Partial<T>>>;
|
|
214
300
|
/**
|
|
215
301
|
* Updates an entity instance with new values, respecting preventUpdates flags on properties
|
|
216
302
|
*
|
|
@@ -312,6 +398,11 @@ export declare class EntityUtils {
|
|
|
312
398
|
* @private
|
|
313
399
|
*/
|
|
314
400
|
private static runPropertyValidators;
|
|
401
|
+
/**
|
|
402
|
+
* Validates all properties on an object (entity instance or plain object)
|
|
403
|
+
* @private
|
|
404
|
+
*/
|
|
405
|
+
private static validateProperties;
|
|
315
406
|
private static addInjectedDependencies;
|
|
316
407
|
/**
|
|
317
408
|
* Validates an entity instance by running all property and entity validators
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,YAAY,EAGZ,eAAe,EACf,mBAAmB,EACpB,MAAM,YAAY,CAAC;AASpB,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;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAa/B;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,kBAAkB,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO;IAU1D,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4DG;IACH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO;IAyCnD;;;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,YAAY,GAAE,YAAiB,GAC9B,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/entity-utils.js
CHANGED
|
@@ -316,49 +316,9 @@ export class EntityUtils {
|
|
|
316
316
|
throw new Error(`Cannot serialize value of type '${typeof value}'. Use passthrough: true in @Property() to explicitly allow serialization of unknown types.`);
|
|
317
317
|
}
|
|
318
318
|
/**
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
|
|
322
|
-
* @param plainObject - The plain object to deserialize
|
|
323
|
-
* @param parseOptions - Parse options (strict mode)
|
|
324
|
-
* @returns Promise resolving to a new instance of the entity with deserialized values
|
|
325
|
-
*
|
|
326
|
-
* @remarks
|
|
327
|
-
* Deserialization rules:
|
|
328
|
-
* - All @Property() decorators must include type metadata for parse() to work
|
|
329
|
-
* - Properties without type metadata will throw an error
|
|
330
|
-
* - Required properties (optional !== true) must be present and not null/undefined
|
|
331
|
-
* - Optional properties (optional === true) can be undefined or null
|
|
332
|
-
* - Arrays are supported with the array: true option
|
|
333
|
-
* - Nested entities are recursively deserialized
|
|
334
|
-
* - Type conversion is strict (no coercion)
|
|
335
|
-
* - Entity constructors must accept a required data parameter
|
|
336
|
-
*
|
|
337
|
-
* Validation behavior:
|
|
338
|
-
* - If strict: true - both HARD and SOFT problems throw ValidationError
|
|
339
|
-
* - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored
|
|
340
|
-
* - Property validators run first, then entity validators
|
|
341
|
-
* - Validators can be synchronous or asynchronous
|
|
342
|
-
* - Problems are accessible via EntityUtils.getProblems()
|
|
343
|
-
* - Raw input data is accessible via EntityUtils.getRawInput()
|
|
344
|
-
*
|
|
345
|
-
* @example
|
|
346
|
-
* ```typescript
|
|
347
|
-
* @Entity()
|
|
348
|
-
* class User {
|
|
349
|
-
* @Property({ type: () => String }) name!: string;
|
|
350
|
-
* @Property({ type: () => Number }) age!: number;
|
|
351
|
-
*
|
|
352
|
-
* constructor(data: Partial<User>) {
|
|
353
|
-
* Object.assign(this, data);
|
|
354
|
-
* }
|
|
355
|
-
* }
|
|
356
|
-
*
|
|
357
|
-
* const json = { name: 'John', age: 30 };
|
|
358
|
-
* const user = await EntityUtils.parse(User, json);
|
|
359
|
-
* const userStrict = await EntityUtils.parse(User, json, { strict: true });
|
|
360
|
-
* ```
|
|
361
|
-
*/ static async parse(entityClass, plainObject, parseOptions = {}) {
|
|
319
|
+
* Internal parse implementation with extended options
|
|
320
|
+
* @private
|
|
321
|
+
*/ static async _parseInternal(entityClass, plainObject, options = {}) {
|
|
362
322
|
if (this.isCollectionEntity(entityClass)) {
|
|
363
323
|
plainObject = {
|
|
364
324
|
collection: plainObject
|
|
@@ -373,7 +333,9 @@ export class EntityUtils {
|
|
|
373
333
|
if (typeof plainObject !== 'object') {
|
|
374
334
|
throw createValidationError(`Expects an object but received ${typeof plainObject}`);
|
|
375
335
|
}
|
|
376
|
-
const strict =
|
|
336
|
+
const strict = options.strict ?? false;
|
|
337
|
+
const skipDefaults = options.skipDefaults ?? false;
|
|
338
|
+
const skipMissing = options.skipMissing ?? false;
|
|
377
339
|
const keys = this.getPropertyKeys(entityClass.prototype);
|
|
378
340
|
const data = {};
|
|
379
341
|
const hardProblems = [];
|
|
@@ -393,8 +355,11 @@ export class EntityUtils {
|
|
|
393
355
|
}
|
|
394
356
|
const isOptional = propertyOptions.optional === true;
|
|
395
357
|
if (!(key in plainObject) || value == null) {
|
|
358
|
+
if (skipMissing) {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
396
361
|
let valueToSet = value;
|
|
397
|
-
if (propertyOptions.default !== undefined) {
|
|
362
|
+
if (!skipDefaults && propertyOptions.default !== undefined) {
|
|
398
363
|
valueToSet = typeof propertyOptions.default === 'function' ? await propertyOptions.default() : propertyOptions.default;
|
|
399
364
|
}
|
|
400
365
|
if (!isOptional && valueToSet == null) {
|
|
@@ -407,7 +372,10 @@ export class EntityUtils {
|
|
|
407
372
|
continue;
|
|
408
373
|
}
|
|
409
374
|
try {
|
|
410
|
-
|
|
375
|
+
// Only pass strict to nested deserialization, not skipDefaults/skipMissing
|
|
376
|
+
data[key] = await this.deserializeValue(value, propertyOptions, {
|
|
377
|
+
strict
|
|
378
|
+
});
|
|
411
379
|
} catch (error) {
|
|
412
380
|
if (error instanceof ValidationError) {
|
|
413
381
|
const problems = prependPropertyPath(key, error);
|
|
@@ -422,6 +390,59 @@ export class EntityUtils {
|
|
|
422
390
|
}
|
|
423
391
|
}
|
|
424
392
|
}
|
|
393
|
+
return {
|
|
394
|
+
data,
|
|
395
|
+
hardProblems
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Deserializes a plain object to an entity instance
|
|
400
|
+
*
|
|
401
|
+
* @param entityClass - The entity class constructor. Must accept a data object parameter.
|
|
402
|
+
* @param plainObject - The plain object to deserialize
|
|
403
|
+
* @param parseOptions - Parse options (strict mode)
|
|
404
|
+
* @returns Promise resolving to a new instance of the entity with deserialized values
|
|
405
|
+
*
|
|
406
|
+
* @remarks
|
|
407
|
+
* Deserialization rules:
|
|
408
|
+
* - All @Property() decorators must include type metadata for parse() to work
|
|
409
|
+
* - Properties without type metadata will throw an error
|
|
410
|
+
* - Required properties (optional !== true) must be present and not null/undefined
|
|
411
|
+
* - Optional properties (optional === true) can be undefined or null
|
|
412
|
+
* - Arrays are supported with the array: true option
|
|
413
|
+
* - Nested entities are recursively deserialized
|
|
414
|
+
* - Type conversion is strict (no coercion)
|
|
415
|
+
* - Entity constructors must accept a required data parameter
|
|
416
|
+
*
|
|
417
|
+
* Validation behavior:
|
|
418
|
+
* - If strict: true - both HARD and SOFT problems throw ValidationError
|
|
419
|
+
* - If strict: false (default) - HARD problems throw ValidationError, SOFT problems stored
|
|
420
|
+
* - Property validators run first, then entity validators
|
|
421
|
+
* - Validators can be synchronous or asynchronous
|
|
422
|
+
* - Problems are accessible via EntityUtils.getProblems()
|
|
423
|
+
* - Raw input data is accessible via EntityUtils.getRawInput()
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```typescript
|
|
427
|
+
* @Entity()
|
|
428
|
+
* class User {
|
|
429
|
+
* @Property({ type: () => String }) name!: string;
|
|
430
|
+
* @Property({ type: () => Number }) age!: number;
|
|
431
|
+
*
|
|
432
|
+
* constructor(data: Partial<User>) {
|
|
433
|
+
* Object.assign(this, data);
|
|
434
|
+
* }
|
|
435
|
+
* }
|
|
436
|
+
*
|
|
437
|
+
* const json = { name: 'John', age: 30 };
|
|
438
|
+
* const user = await EntityUtils.parse(User, json);
|
|
439
|
+
* const userStrict = await EntityUtils.parse(User, json, { strict: true });
|
|
440
|
+
* ```
|
|
441
|
+
*/ static async parse(entityClass, plainObject, parseOptions = {}) {
|
|
442
|
+
const strict = parseOptions?.strict ?? false;
|
|
443
|
+
const { data, hardProblems } = await this._parseInternal(entityClass, plainObject, {
|
|
444
|
+
strict
|
|
445
|
+
});
|
|
425
446
|
if (hardProblems.length > 0) {
|
|
426
447
|
throw new ValidationError(hardProblems);
|
|
427
448
|
}
|
|
@@ -492,6 +513,119 @@ export class EntityUtils {
|
|
|
492
513
|
}
|
|
493
514
|
}
|
|
494
515
|
/**
|
|
516
|
+
* Partially deserializes a plain object, returning a plain object with only present properties
|
|
517
|
+
*
|
|
518
|
+
* @param entityClass - The entity class constructor
|
|
519
|
+
* @param plainObject - The plain object to deserialize
|
|
520
|
+
* @param options - Options with strict mode
|
|
521
|
+
* @returns Promise resolving to a plain object with deserialized properties (Partial<T>)
|
|
522
|
+
*
|
|
523
|
+
* @remarks
|
|
524
|
+
* Differences from parse():
|
|
525
|
+
* - Returns a plain object, not an entity instance
|
|
526
|
+
* - Ignores missing properties (does not include them in result)
|
|
527
|
+
* - Does NOT apply default values to missing properties
|
|
528
|
+
* - When strict: false (default), properties with HARD problems are excluded from result but problems are tracked
|
|
529
|
+
* - When strict: true, any HARD problem throws ValidationError
|
|
530
|
+
* - Nested entities/arrays are still fully deserialized and validated as normal
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```typescript
|
|
534
|
+
* @Entity()
|
|
535
|
+
* class User {
|
|
536
|
+
* @Property({ type: () => String }) name!: string;
|
|
537
|
+
* @Property({ type: () => Number, default: 0 }) age!: number;
|
|
538
|
+
*
|
|
539
|
+
* constructor(data: Partial<User>) {
|
|
540
|
+
* Object.assign(this, data);
|
|
541
|
+
* }
|
|
542
|
+
* }
|
|
543
|
+
*
|
|
544
|
+
* const partial = await EntityUtils.partialParse(User, { name: 'John' });
|
|
545
|
+
* // partial = { name: 'John' } (age is not included, default not applied)
|
|
546
|
+
*
|
|
547
|
+
* const partialWithError = await EntityUtils.partialParse(User, { name: 'John', age: 'invalid' });
|
|
548
|
+
* // partialWithError = { name: 'John' } (age excluded due to HARD problem)
|
|
549
|
+
* // Access problems via second return value
|
|
550
|
+
* ```
|
|
551
|
+
*/ static async partialParse(entityClass, plainObject, options = {}) {
|
|
552
|
+
const result = await this.safePartialParse(entityClass, plainObject, options);
|
|
553
|
+
if (!result.success) {
|
|
554
|
+
throw new ValidationError(result.problems);
|
|
555
|
+
}
|
|
556
|
+
return result.data;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Safely performs partial deserialization without throwing errors
|
|
560
|
+
*
|
|
561
|
+
* @param entityClass - The entity class constructor
|
|
562
|
+
* @param plainObject - The plain object to deserialize
|
|
563
|
+
* @param options - Options with strict mode
|
|
564
|
+
* @returns Promise resolving to a result object with success flag, partial data, and problems
|
|
565
|
+
*
|
|
566
|
+
* @remarks
|
|
567
|
+
* Similar to partialParse() but returns a result object instead of throwing errors:
|
|
568
|
+
* - On success with strict: true - returns { success: true, data: Partial<T>, problems: [] }
|
|
569
|
+
* - On success with strict: false - returns { success: true, data: Partial<T>, problems: [...] } (includes hard problems for excluded properties)
|
|
570
|
+
* - On failure (strict mode only) - returns { success: false, data: undefined, problems: [...] }
|
|
571
|
+
*
|
|
572
|
+
* All partial deserialization rules from partialParse() apply.
|
|
573
|
+
* See partialParse() documentation for detailed behavior.
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* ```typescript
|
|
577
|
+
* @Entity()
|
|
578
|
+
* class User {
|
|
579
|
+
* @Property({ type: () => String }) name!: string;
|
|
580
|
+
* @Property({ type: () => Number }) age!: number;
|
|
581
|
+
*
|
|
582
|
+
* constructor(data: Partial<User>) {
|
|
583
|
+
* Object.assign(this, data);
|
|
584
|
+
* }
|
|
585
|
+
* }
|
|
586
|
+
*
|
|
587
|
+
* const result = await EntityUtils.safePartialParse(User, { name: 'John', age: 'invalid' });
|
|
588
|
+
* if (result.success) {
|
|
589
|
+
* console.log(result.data); // { name: 'John' }
|
|
590
|
+
* console.log(result.problems); // [Problem for age property]
|
|
591
|
+
* } else {
|
|
592
|
+
* console.log(result.problems); // Hard problems (only in strict mode)
|
|
593
|
+
* }
|
|
594
|
+
* ```
|
|
595
|
+
*/ static async safePartialParse(entityClass, plainObject, options) {
|
|
596
|
+
const strict = options?.strict ?? false;
|
|
597
|
+
const { data, hardProblems } = await this._parseInternal(entityClass, plainObject, {
|
|
598
|
+
strict,
|
|
599
|
+
skipDefaults: true,
|
|
600
|
+
skipMissing: true
|
|
601
|
+
});
|
|
602
|
+
if (strict && hardProblems.length > 0) {
|
|
603
|
+
return {
|
|
604
|
+
success: false,
|
|
605
|
+
data: undefined,
|
|
606
|
+
problems: hardProblems
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
const propertyProblems = await this.validateProperties(data, entityClass.prototype);
|
|
610
|
+
const validationProblems = [
|
|
611
|
+
...hardProblems,
|
|
612
|
+
...propertyProblems
|
|
613
|
+
];
|
|
614
|
+
if (strict && propertyProblems.length > 0) {
|
|
615
|
+
return {
|
|
616
|
+
success: false,
|
|
617
|
+
data: undefined,
|
|
618
|
+
problems: validationProblems
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
this.setProblems(data, validationProblems);
|
|
622
|
+
return {
|
|
623
|
+
success: true,
|
|
624
|
+
data: data,
|
|
625
|
+
problems: validationProblems
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
495
629
|
* Updates an entity instance with new values, respecting preventUpdates flags on properties
|
|
496
630
|
*
|
|
497
631
|
* @param instance - The entity instance to update. Must be an Entity.
|
|
@@ -742,6 +876,24 @@ export class EntityUtils {
|
|
|
742
876
|
}
|
|
743
877
|
return problems;
|
|
744
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Validates all properties on an object (entity instance or plain object)
|
|
881
|
+
* @private
|
|
882
|
+
*/ static async validateProperties(dataOrInstance, prototype) {
|
|
883
|
+
const problems = [];
|
|
884
|
+
const keys = Object.keys(dataOrInstance);
|
|
885
|
+
for (const key of keys){
|
|
886
|
+
const options = this.getPropertyOptions(prototype, key);
|
|
887
|
+
if (options) {
|
|
888
|
+
const value = dataOrInstance[key];
|
|
889
|
+
if (value != null) {
|
|
890
|
+
const validationProblems = await this.runPropertyValidators(key, value, options);
|
|
891
|
+
problems.push(...validationProblems);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return problems;
|
|
896
|
+
}
|
|
745
897
|
static async addInjectedDependencies(data, prototype) {
|
|
746
898
|
const injectedPropertyNames = getInjectedPropertyNames(prototype);
|
|
747
899
|
if (injectedPropertyNames.length === 0) {
|
|
@@ -778,17 +930,8 @@ export class EntityUtils {
|
|
|
778
930
|
throw new Error('Cannot validate non-entity instance');
|
|
779
931
|
}
|
|
780
932
|
const problems = [];
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
const options = this.getPropertyOptions(instance, key);
|
|
784
|
-
if (options) {
|
|
785
|
-
const value = instance[key];
|
|
786
|
-
if (value != null) {
|
|
787
|
-
const validationProblems = await this.runPropertyValidators(key, value, options);
|
|
788
|
-
problems.push(...validationProblems);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
933
|
+
const propertyProblems = await this.validateProperties(instance, instance);
|
|
934
|
+
problems.push(...propertyProblems);
|
|
792
935
|
const entityValidators = this.getEntityValidators(instance);
|
|
793
936
|
for (const validatorMethod of entityValidators){
|
|
794
937
|
const validatorProblems = await instance[validatorMethod]();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/entity-utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_OPTIONS_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n ParseOptions,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n SafeOperationResult,\n} from './types.js';\nimport type { EntityOptions } from './entity.js';\nimport {\n getInjectedPropertyNames,\n getInjectedPropertyOptions,\n} from './injected-property.js';\nimport { EntityDI } from './entity-di.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, 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 /**\n * Gets the entity options for a given constructor\n *\n * @param entityOrClass - The entity class constructor or instance\n * @returns EntityOptions object (empty object if no options are defined)\n * @private\n */\n private static getEntityOptions(entityOrClass: unknown): EntityOptions {\n const constructor =\n typeof entityOrClass === 'function'\n ? entityOrClass\n : Object.getPrototypeOf(entityOrClass).constructor;\n\n const options: EntityOptions | undefined = Reflect.getMetadata(\n ENTITY_OPTIONS_METADATA_KEY,\n constructor,\n );\n return options ?? {};\n }\n\n /**\n * Checks if a given entity is marked as a collection entity\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns true if the entity is a collection entity, false otherwise\n *\n * @example\n * ```typescript\n * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n *\n * const tags = new Tags({ collection: ['a', 'b'] });\n * console.log(EntityUtils.isCollectionEntity(tags)); // true\n * console.log(EntityUtils.isCollectionEntity(Tags)); // true\n * ```\n */\n static isCollectionEntity(entityOrClass: unknown): boolean {\n if (!this.isEntity(entityOrClass)) {\n return false;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n\n return options.collection === true;\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, or an array for collection entities\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 * - Collection entities (@CollectionEntity) are unwrapped to just their array\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 * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n *\n * const tags = new Tags({ collection: ['a', 'b'] });\n * const json = EntityUtils.toJSON(tags);\n * // ['a', 'b'] - unwrapped to array\n * ```\n */\n static toJSON<T extends object>(entity: T): unknown {\n if (this.isCollectionEntity(entity)) {\n const collectionPropertyOptions = this.getPropertyOptions(\n entity,\n 'collection',\n );\n if (!collectionPropertyOptions) {\n throw new Error(\n `Collection entity 'collection' property is missing metadata`,\n );\n }\n if (!collectionPropertyOptions.array) {\n throw new Error(\n `Collection entity 'collection' property must be an array`,\n );\n }\n\n return this.serializeValue(\n (entity as any).collection,\n collectionPropertyOptions,\n );\n }\n\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 parseOptions - 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.getProblems()\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 parseOptions: ParseOptions = {},\n ): Promise<T> {\n if (this.isCollectionEntity(entityClass)) {\n plainObject = { collection: plainObject };\n }\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 = parseOptions?.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) || value == null) {\n let valueToSet = value;\n\n if (propertyOptions.default !== undefined) {\n valueToSet =\n typeof propertyOptions.default === 'function'\n ? await propertyOptions.default()\n : propertyOptions.default;\n }\n\n if (!isOptional && valueToSet == null) {\n hardProblems.push(\n new Problem({\n property: key,\n message:\n 'Required property is missing, null or undefined from input',\n }),\n );\n }\n data[key] = valueToSet;\n continue;\n }\n\n try {\n data[key] = await this.deserializeValue(\n value,\n propertyOptions,\n parseOptions,\n );\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 await this.addInjectedDependencies(data, entityClass.prototype);\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 && strict) {\n throw new ValidationError(problems);\n }\n\n return instance;\n }\n\n /**\n * Safely deserializes a plain object to an entity instance without throwing errors\n *\n * @param entityClass - The entity class constructor. Must accept a data object parameter.\n * @param plainObject - The plain object to deserialize\n * @param parseOptions - Parse options (strict mode)\n * @returns Promise resolving to a result object with success flag, data, and problems\n *\n * @remarks\n * Similar to parse() but returns a result object instead of throwing errors:\n * - On success with strict: true - returns { success: true, data, problems: [] }\n * - On success with strict: false - returns { success: true, data, problems: [...] } (may include soft problems)\n * - On failure - returns { success: false, data: undefined, problems: [...] }\n *\n * All deserialization and validation rules from parse() apply.\n * See parse() documentation for detailed deserialization behavior.\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 result = await EntityUtils.safeParse(User, { name: 'John', age: 30 });\n * if (result.success) {\n * console.log(result.data); // User instance\n * console.log(result.problems); // [] or soft problems if not strict\n * } else {\n * console.log(result.problems); // Hard problems\n * }\n * ```\n */\n static async safeParse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n parseOptions?: ParseOptions,\n ): SafeOperationResult<T> {\n try {\n const data = await this.parse(entityClass, plainObject, parseOptions);\n const problems = this.getProblems(data);\n\n return {\n success: true,\n data,\n problems,\n };\n } catch (error) {\n if (error instanceof ValidationError) {\n return {\n success: false,\n data: undefined,\n problems: error.problems,\n };\n }\n throw error;\n }\n }\n\n /**\n * Updates an entity instance with new values, respecting preventUpdates flags on properties\n *\n * @param instance - The entity instance to update. Must be an Entity.\n * @param updates - Partial object with properties to update\n * @param options - Update options (strict mode)\n * @returns Promise resolving to a new instance with updated values\n *\n * @remarks\n * Update behavior:\n * - Creates a shallow copy of the instance\n * - For each @Property(), copies the value from updates if it exists\n * - Properties with preventUpdates: true will not be copied from updates\n * - Runs entity validators after applying updates\n * - Throws ValidationError if validation fails and strict: true\n * - Soft problems are stored on the instance if strict: false (default)\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n * @Property({ type: () => String, preventUpdates: true }) id!: string;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const user = new User({ id: '123', name: 'John' });\n * const updated = await EntityUtils.update(user, { id: '456', name: 'Jane' });\n * // updated.id === '123' (not updated due to preventUpdates: true)\n * // updated.name === 'Jane'\n * ```\n */\n static async update<T extends object>(\n instance: T,\n updates: Partial<T>,\n options?: { strict?: boolean },\n ): Promise<T> {\n if (!this.isEntity(instance)) {\n throw new Error('Cannot update non-entity instance');\n }\n\n const strict = options?.strict ?? false;\n const Constructor = Object.getPrototypeOf(instance).constructor;\n const keys = this.getPropertyKeys(instance);\n const data: Record<string, unknown> = {};\n\n // Copy existing properties\n for (const key of keys) {\n const value = (instance as any)[key];\n data[key] = value;\n }\n\n // Apply updates, respecting preventUpdates flag\n for (const key of keys) {\n if (key in updates) {\n const propertyOptions = this.getPropertyOptions(instance, key);\n if (propertyOptions && propertyOptions.preventUpdates === true) {\n // Skip updating this property\n continue;\n }\n data[key] = (updates as any)[key];\n }\n }\n\n const newInstance = new Constructor(data);\n\n const problems = await this.validate(newInstance);\n\n if (problems.length > 0 && strict) {\n throw new ValidationError(problems);\n }\n\n return newInstance;\n }\n\n /**\n * Safely updates an entity instance without throwing errors\n *\n * @param instance - The entity instance to update. Must be an Entity.\n * @param updates - Partial object with properties to update\n * @param options - Update options (strict mode)\n * @returns Promise resolving to a result object with success flag, data, and problems\n *\n * @remarks\n * Similar to update() but returns a result object instead of throwing errors:\n * - On success with strict: true - returns { success: true, data, problems: [] }\n * - On success with strict: false - returns { success: true, data, problems: [...] } (may include soft problems)\n * - On failure - returns { success: false, data: undefined, problems: [...] }\n *\n * All update and validation rules from update() apply.\n * See update() documentation for detailed update behavior.\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const user = new User({ name: 'John' });\n * const result = await EntityUtils.safeUpdate(user, { name: 'Jane' });\n * if (result.success) {\n * console.log(result.data); // Updated User instance\n * console.log(result.problems); // [] or soft problems if not strict\n * } else {\n * console.log(result.problems); // Hard problems\n * }\n * ```\n */\n static async safeUpdate<T extends object>(\n instance: T,\n updates: Partial<T>,\n options?: { strict?: boolean },\n ): SafeOperationResult<T> {\n try {\n const updatedInstance = await this.update(instance, updates, options);\n const problems = this.getProblems(updatedInstance);\n\n return {\n success: true,\n data: updatedInstance,\n problems,\n };\n } catch (error) {\n if (error instanceof ValidationError) {\n return {\n success: false,\n data: undefined,\n problems: error.problems,\n };\n }\n throw error;\n }\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 parseOptions: ParseOptions,\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(\n item,\n typeConstructor,\n parseOptions,\n ),\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(\n value,\n typeConstructor,\n parseOptions,\n );\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 parseOptions: ParseOptions,\n ): Promise<unknown> {\n if (isPrimitiveConstructor(typeConstructor)) {\n return deserializePrimitive(value, typeConstructor);\n }\n\n if (this.isEntity(typeConstructor)) {\n return await this.parse(\n typeConstructor as new (data: any) => object,\n value as Record<string, unknown>,\n parseOptions,\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 existingProblems = problemsStorage.get(value);\n const nestedProblems =\n existingProblems && existingProblems.length > 0\n ? existingProblems\n : await EntityUtils.validate(value);\n\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 private static async addInjectedDependencies(\n data: Record<string, unknown>,\n prototype: object,\n ): Promise<void> {\n const injectedPropertyNames = getInjectedPropertyNames(prototype);\n if (injectedPropertyNames.length === 0) {\n return;\n }\n\n const injectedPropertyOptions = getInjectedPropertyOptions(prototype);\n\n for (const propertyName of injectedPropertyNames) {\n const token = injectedPropertyOptions[propertyName];\n if (token) {\n const dependency = await EntityDI.get(token);\n data[propertyName] = dependency;\n }\n }\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 EntityUtils.setProblems(instance, problems);\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.getProblems(user);\n * console.log(problems); // [Problem, ...]\n * ```\n */\n static getProblems<T extends object>(instance: T): Problem[] {\n return problemsStorage.get(instance) || [];\n }\n\n /**\n * Sets the validation problems for an entity instance\n *\n * @param instance - The entity instance\n * @param problems - Array of Problems to associate with the instance\n *\n * @remarks\n * - Overwrites any existing problems for the instance\n * - Pass an empty array to clear problems\n *\n * @example\n * ```typescript\n * const user = new User({ name: 'John' });\n * EntityUtils.setProblems(user, [new Problem({ property: 'name', message: 'Invalid name' })]);\n * ```\n */\n static setProblems<T extends object>(instance: T, problems: Problem[]): void {\n if (problems.length === 0) {\n problemsStorage.delete(instance);\n } else {\n problemsStorage.set(instance, problems);\n }\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>(instance: T): unknown {\n return rawInputStorage.get(instance);\n }\n\n /**\n * Sets the raw input data for an entity instance\n *\n * @param instance - The entity instance\n * @param rawInput - The raw input object to associate with the instance\n *\n * @remarks\n * - Overwrites any existing raw input for the instance\n * - Pass undefined to clear the raw input\n *\n * @example\n * ```typescript\n * const user = new User({ name: 'John' });\n * EntityUtils.setRawInput(user, { name: 'John', age: 30 });\n * ```\n */\n static setRawInput<T extends object>(\n instance: T,\n rawInput: Record<string, unknown> | undefined,\n ): void {\n if (rawInput === undefined) {\n rawInputStorage.delete(instance);\n } else {\n rawInputStorage.set(instance, rawInput);\n }\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_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","getInjectedPropertyNames","getInjectedPropertyOptions","EntityDI","isEqualWith","ValidationError","Problem","prependPropertyPath","prependArrayIndex","createValidationError","combinePropertyPaths","isPrimitiveConstructor","deserializePrimitive","ok","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","getEntityOptions","entityOrClass","options","getMetadata","isCollectionEntity","collection","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","collectionPropertyOptions","array","serializeValue","result","value","passthrough","serialize","map","item","Date","toISOString","toString","parse","entityClass","plainObject","parseOptions","strict","data","hardProblems","message","isOptional","optional","valueToSet","default","deserializeValue","error","problems","addInjectedDependencies","instance","set","validate","safeParse","getProblems","success","update","updates","Constructor","preventUpdates","newInstance","safeUpdate","updatedInstance","typeConstructor","type","isSparse","sparse","arrayProblems","index","deserialize","deserializeSingleValue","validatePropertyValue","propertyPath","validators","validator","validatorProblems","problem","existingProblems","get","nestedProblems","prependedProblems","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","element","elementPath","elementProblems","injectedPropertyNames","injectedPropertyOptions","propertyName","token","dependency","validationProblems","entityValidators","getEntityValidators","validatorMethod","setProblems","delete","getRawInput","setRawInput","rawInput","protoValidators"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/entity-utils.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_OPTIONS_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n ParseOptions,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n SafeOperationResult,\n} from './types.js';\nimport type { EntityOptions } from './entity.js';\nimport {\n getInjectedPropertyNames,\n getInjectedPropertyOptions,\n} from './injected-property.js';\nimport { EntityDI } from './entity-di.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, 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 /**\n * Gets the entity options for a given constructor\n *\n * @param entityOrClass - The entity class constructor or instance\n * @returns EntityOptions object (empty object if no options are defined)\n * @private\n */\n private static getEntityOptions(entityOrClass: unknown): EntityOptions {\n const constructor =\n typeof entityOrClass === 'function'\n ? entityOrClass\n : Object.getPrototypeOf(entityOrClass).constructor;\n\n const options: EntityOptions | undefined = Reflect.getMetadata(\n ENTITY_OPTIONS_METADATA_KEY,\n constructor,\n );\n return options ?? {};\n }\n\n /**\n * Checks if a given entity is marked as a collection entity\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns true if the entity is a collection entity, false otherwise\n *\n * @example\n * ```typescript\n * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n *\n * const tags = new Tags({ collection: ['a', 'b'] });\n * console.log(EntityUtils.isCollectionEntity(tags)); // true\n * console.log(EntityUtils.isCollectionEntity(Tags)); // true\n * ```\n */\n static isCollectionEntity(entityOrClass: unknown): boolean {\n if (!this.isEntity(entityOrClass)) {\n return false;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n\n return options.collection === true;\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, or an array for collection entities\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 * - Collection entities (@CollectionEntity) are unwrapped to just their array\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 * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n *\n * const tags = new Tags({ collection: ['a', 'b'] });\n * const json = EntityUtils.toJSON(tags);\n * // ['a', 'b'] - unwrapped to array\n * ```\n */\n static toJSON<T extends object>(entity: T): unknown {\n if (this.isCollectionEntity(entity)) {\n const collectionPropertyOptions = this.getPropertyOptions(\n entity,\n 'collection',\n );\n if (!collectionPropertyOptions) {\n throw new Error(\n `Collection entity 'collection' property is missing metadata`,\n );\n }\n if (!collectionPropertyOptions.array) {\n throw new Error(\n `Collection entity 'collection' property must be an array`,\n );\n }\n\n return this.serializeValue(\n (entity as any).collection,\n collectionPropertyOptions,\n );\n }\n\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 * Internal parse implementation with extended options\n * @private\n */\n private static async _parseInternal<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n options: {\n strict?: boolean;\n skipDefaults?: boolean;\n skipMissing?: boolean;\n } = {},\n ): Promise<{ data: Record<string, unknown>; hardProblems: Problem[] }> {\n if (this.isCollectionEntity(entityClass)) {\n plainObject = { collection: plainObject };\n }\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 skipDefaults = options.skipDefaults ?? false;\n const skipMissing = options.skipMissing ?? 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) || value == null) {\n if (skipMissing) {\n continue;\n }\n\n let valueToSet = value;\n\n if (!skipDefaults && propertyOptions.default !== undefined) {\n valueToSet =\n typeof propertyOptions.default === 'function'\n ? await propertyOptions.default()\n : propertyOptions.default;\n }\n\n if (!isOptional && valueToSet == null) {\n hardProblems.push(\n new Problem({\n property: key,\n message:\n 'Required property is missing, null or undefined from input',\n }),\n );\n }\n data[key] = valueToSet;\n continue;\n }\n\n try {\n // Only pass strict to nested deserialization, not skipDefaults/skipMissing\n data[key] = await this.deserializeValue(value, propertyOptions, {\n strict,\n });\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 return { data, hardProblems };\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 parseOptions - 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.getProblems()\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 parseOptions: ParseOptions = {},\n ): Promise<T> {\n const strict = parseOptions?.strict ?? false;\n\n const { data, hardProblems } = await this._parseInternal(\n entityClass,\n plainObject,\n { strict },\n );\n\n if (hardProblems.length > 0) {\n throw new ValidationError(hardProblems);\n }\n\n await this.addInjectedDependencies(data, entityClass.prototype);\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 && strict) {\n throw new ValidationError(problems);\n }\n\n return instance;\n }\n\n /**\n * Safely deserializes a plain object to an entity instance without throwing errors\n *\n * @param entityClass - The entity class constructor. Must accept a data object parameter.\n * @param plainObject - The plain object to deserialize\n * @param parseOptions - Parse options (strict mode)\n * @returns Promise resolving to a result object with success flag, data, and problems\n *\n * @remarks\n * Similar to parse() but returns a result object instead of throwing errors:\n * - On success with strict: true - returns { success: true, data, problems: [] }\n * - On success with strict: false - returns { success: true, data, problems: [...] } (may include soft problems)\n * - On failure - returns { success: false, data: undefined, problems: [...] }\n *\n * All deserialization and validation rules from parse() apply.\n * See parse() documentation for detailed deserialization behavior.\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 result = await EntityUtils.safeParse(User, { name: 'John', age: 30 });\n * if (result.success) {\n * console.log(result.data); // User instance\n * console.log(result.problems); // [] or soft problems if not strict\n * } else {\n * console.log(result.problems); // Hard problems\n * }\n * ```\n */\n static async safeParse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n parseOptions?: ParseOptions,\n ): SafeOperationResult<T> {\n try {\n const data = await this.parse(entityClass, plainObject, parseOptions);\n const problems = this.getProblems(data);\n\n return {\n success: true,\n data,\n problems,\n };\n } catch (error) {\n if (error instanceof ValidationError) {\n return {\n success: false,\n data: undefined,\n problems: error.problems,\n };\n }\n throw error;\n }\n }\n\n /**\n * Partially deserializes a plain object, returning a plain object with only present properties\n *\n * @param entityClass - The entity class constructor\n * @param plainObject - The plain object to deserialize\n * @param options - Options with strict mode\n * @returns Promise resolving to a plain object with deserialized properties (Partial<T>)\n *\n * @remarks\n * Differences from parse():\n * - Returns a plain object, not an entity instance\n * - Ignores missing properties (does not include them in result)\n * - Does NOT apply default values to missing properties\n * - When strict: false (default), properties with HARD problems are excluded from result but problems are tracked\n * - When strict: true, any HARD problem throws ValidationError\n * - Nested entities/arrays are still fully deserialized and validated as normal\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n * @Property({ type: () => Number, default: 0 }) age!: number;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const partial = await EntityUtils.partialParse(User, { name: 'John' });\n * // partial = { name: 'John' } (age is not included, default not applied)\n *\n * const partialWithError = await EntityUtils.partialParse(User, { name: 'John', age: 'invalid' });\n * // partialWithError = { name: 'John' } (age excluded due to HARD problem)\n * // Access problems via second return value\n * ```\n */\n static async partialParse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n options: { strict?: boolean } = {},\n ): Promise<Partial<T>> {\n const result = await this.safePartialParse(\n entityClass,\n plainObject,\n options,\n );\n\n if (!result.success) {\n throw new ValidationError(result.problems);\n }\n\n return result.data;\n }\n\n /**\n * Safely performs partial deserialization without throwing errors\n *\n * @param entityClass - The entity class constructor\n * @param plainObject - The plain object to deserialize\n * @param options - Options with strict mode\n * @returns Promise resolving to a result object with success flag, partial data, and problems\n *\n * @remarks\n * Similar to partialParse() but returns a result object instead of throwing errors:\n * - On success with strict: true - returns { success: true, data: Partial<T>, problems: [] }\n * - On success with strict: false - returns { success: true, data: Partial<T>, problems: [...] } (includes hard problems for excluded properties)\n * - On failure (strict mode only) - returns { success: false, data: undefined, problems: [...] }\n *\n * All partial deserialization rules from partialParse() apply.\n * See partialParse() documentation for detailed behavior.\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 result = await EntityUtils.safePartialParse(User, { name: 'John', age: 'invalid' });\n * if (result.success) {\n * console.log(result.data); // { name: 'John' }\n * console.log(result.problems); // [Problem for age property]\n * } else {\n * console.log(result.problems); // Hard problems (only in strict mode)\n * }\n * ```\n */\n static async safePartialParse<T extends object>(\n entityClass: new (data: any) => T,\n plainObject: unknown,\n options?: { strict?: boolean },\n ): Promise<SafeOperationResult<Partial<T>>> {\n const strict = options?.strict ?? false;\n\n const { data, hardProblems } = await this._parseInternal(\n entityClass,\n plainObject,\n { strict, skipDefaults: true, skipMissing: true },\n );\n\n if (strict && hardProblems.length > 0) {\n return {\n success: false,\n data: undefined,\n problems: hardProblems,\n };\n }\n\n const propertyProblems = await this.validateProperties(\n data,\n entityClass.prototype,\n );\n const validationProblems = [...hardProblems, ...propertyProblems];\n\n if (strict && propertyProblems.length > 0) {\n return {\n success: false,\n data: undefined,\n problems: validationProblems,\n };\n }\n\n this.setProblems(data, validationProblems);\n\n return {\n success: true,\n data: data as Partial<T>,\n problems: validationProblems,\n };\n }\n\n /**\n * Updates an entity instance with new values, respecting preventUpdates flags on properties\n *\n * @param instance - The entity instance to update. Must be an Entity.\n * @param updates - Partial object with properties to update\n * @param options - Update options (strict mode)\n * @returns Promise resolving to a new instance with updated values\n *\n * @remarks\n * Update behavior:\n * - Creates a shallow copy of the instance\n * - For each @Property(), copies the value from updates if it exists\n * - Properties with preventUpdates: true will not be copied from updates\n * - Runs entity validators after applying updates\n * - Throws ValidationError if validation fails and strict: true\n * - Soft problems are stored on the instance if strict: false (default)\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n * @Property({ type: () => String, preventUpdates: true }) id!: string;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const user = new User({ id: '123', name: 'John' });\n * const updated = await EntityUtils.update(user, { id: '456', name: 'Jane' });\n * // updated.id === '123' (not updated due to preventUpdates: true)\n * // updated.name === 'Jane'\n * ```\n */\n static async update<T extends object>(\n instance: T,\n updates: Partial<T>,\n options?: { strict?: boolean },\n ): Promise<T> {\n if (!this.isEntity(instance)) {\n throw new Error('Cannot update non-entity instance');\n }\n\n const strict = options?.strict ?? false;\n const Constructor = Object.getPrototypeOf(instance).constructor;\n const keys = this.getPropertyKeys(instance);\n const data: Record<string, unknown> = {};\n\n // Copy existing properties\n for (const key of keys) {\n const value = (instance as any)[key];\n data[key] = value;\n }\n\n // Apply updates, respecting preventUpdates flag\n for (const key of keys) {\n if (key in updates) {\n const propertyOptions = this.getPropertyOptions(instance, key);\n if (propertyOptions && propertyOptions.preventUpdates === true) {\n // Skip updating this property\n continue;\n }\n data[key] = (updates as any)[key];\n }\n }\n\n const newInstance = new Constructor(data);\n\n const problems = await this.validate(newInstance);\n\n if (problems.length > 0 && strict) {\n throw new ValidationError(problems);\n }\n\n return newInstance;\n }\n\n /**\n * Safely updates an entity instance without throwing errors\n *\n * @param instance - The entity instance to update. Must be an Entity.\n * @param updates - Partial object with properties to update\n * @param options - Update options (strict mode)\n * @returns Promise resolving to a result object with success flag, data, and problems\n *\n * @remarks\n * Similar to update() but returns a result object instead of throwing errors:\n * - On success with strict: true - returns { success: true, data, problems: [] }\n * - On success with strict: false - returns { success: true, data, problems: [...] } (may include soft problems)\n * - On failure - returns { success: false, data: undefined, problems: [...] }\n *\n * All update and validation rules from update() apply.\n * See update() documentation for detailed update behavior.\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) name!: string;\n *\n * constructor(data: Partial<User>) {\n * Object.assign(this, data);\n * }\n * }\n *\n * const user = new User({ name: 'John' });\n * const result = await EntityUtils.safeUpdate(user, { name: 'Jane' });\n * if (result.success) {\n * console.log(result.data); // Updated User instance\n * console.log(result.problems); // [] or soft problems if not strict\n * } else {\n * console.log(result.problems); // Hard problems\n * }\n * ```\n */\n static async safeUpdate<T extends object>(\n instance: T,\n updates: Partial<T>,\n options?: { strict?: boolean },\n ): SafeOperationResult<T> {\n try {\n const updatedInstance = await this.update(instance, updates, options);\n const problems = this.getProblems(updatedInstance);\n\n return {\n success: true,\n data: updatedInstance,\n problems,\n };\n } catch (error) {\n if (error instanceof ValidationError) {\n return {\n success: false,\n data: undefined,\n problems: error.problems,\n };\n }\n throw error;\n }\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 parseOptions: ParseOptions,\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(\n item,\n typeConstructor,\n parseOptions,\n ),\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(\n value,\n typeConstructor,\n parseOptions,\n );\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 parseOptions: ParseOptions,\n ): Promise<unknown> {\n if (isPrimitiveConstructor(typeConstructor)) {\n return deserializePrimitive(value, typeConstructor);\n }\n\n if (this.isEntity(typeConstructor)) {\n return await this.parse(\n typeConstructor as new (data: any) => object,\n value as Record<string, unknown>,\n parseOptions,\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 existingProblems = problemsStorage.get(value);\n const nestedProblems =\n existingProblems && existingProblems.length > 0\n ? existingProblems\n : await EntityUtils.validate(value);\n\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 all properties on an object (entity instance or plain object)\n * @private\n */\n private static async validateProperties(\n dataOrInstance: Record<string, unknown> | object,\n prototype: object,\n ): Promise<Problem[]> {\n const problems: Problem[] = [];\n const keys = Object.keys(dataOrInstance);\n\n for (const key of keys) {\n const options = this.getPropertyOptions(prototype, key);\n if (options) {\n const value = (dataOrInstance 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 return problems;\n }\n\n private static async addInjectedDependencies(\n data: Record<string, unknown>,\n prototype: object,\n ): Promise<void> {\n const injectedPropertyNames = getInjectedPropertyNames(prototype);\n if (injectedPropertyNames.length === 0) {\n return;\n }\n\n const injectedPropertyOptions = getInjectedPropertyOptions(prototype);\n\n for (const propertyName of injectedPropertyNames) {\n const token = injectedPropertyOptions[propertyName];\n if (token) {\n const dependency = await EntityDI.get(token);\n data[propertyName] = dependency;\n }\n }\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 propertyProblems = await this.validateProperties(instance, instance);\n problems.push(...propertyProblems);\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 EntityUtils.setProblems(instance, problems);\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.getProblems(user);\n * console.log(problems); // [Problem, ...]\n * ```\n */\n static getProblems<T extends object>(instance: T): Problem[] {\n return problemsStorage.get(instance) || [];\n }\n\n /**\n * Sets the validation problems for an entity instance\n *\n * @param instance - The entity instance\n * @param problems - Array of Problems to associate with the instance\n *\n * @remarks\n * - Overwrites any existing problems for the instance\n * - Pass an empty array to clear problems\n *\n * @example\n * ```typescript\n * const user = new User({ name: 'John' });\n * EntityUtils.setProblems(user, [new Problem({ property: 'name', message: 'Invalid name' })]);\n * ```\n */\n static setProblems<T extends object>(instance: T, problems: Problem[]): void {\n if (problems.length === 0) {\n problemsStorage.delete(instance);\n } else {\n problemsStorage.set(instance, problems);\n }\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>(instance: T): unknown {\n return rawInputStorage.get(instance);\n }\n\n /**\n * Sets the raw input data for an entity instance\n *\n * @param instance - The entity instance\n * @param rawInput - The raw input object to associate with the instance\n *\n * @remarks\n * - Overwrites any existing raw input for the instance\n * - Pass undefined to clear the raw input\n *\n * @example\n * ```typescript\n * const user = new User({ name: 'John' });\n * EntityUtils.setRawInput(user, { name: 'John', age: 30 });\n * ```\n */\n static setRawInput<T extends object>(\n instance: T,\n rawInput: Record<string, unknown> | undefined,\n ): void {\n if (rawInput === undefined) {\n rawInputStorage.delete(instance);\n } else {\n rawInputStorage.set(instance, rawInput);\n }\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_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","getInjectedPropertyNames","getInjectedPropertyOptions","EntityDI","isEqualWith","ValidationError","Problem","prependPropertyPath","prependArrayIndex","createValidationError","combinePropertyPaths","isPrimitiveConstructor","deserializePrimitive","ok","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","getEntityOptions","entityOrClass","options","getMetadata","isCollectionEntity","collection","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","collectionPropertyOptions","array","serializeValue","result","value","passthrough","serialize","map","item","Date","toISOString","toString","_parseInternal","entityClass","plainObject","strict","skipDefaults","skipMissing","data","hardProblems","message","isOptional","optional","valueToSet","default","deserializeValue","error","problems","parse","parseOptions","addInjectedDependencies","instance","set","validate","safeParse","getProblems","success","partialParse","safePartialParse","propertyProblems","validateProperties","validationProblems","setProblems","update","updates","Constructor","preventUpdates","newInstance","safeUpdate","updatedInstance","typeConstructor","type","isSparse","sparse","arrayProblems","index","deserialize","deserializeSingleValue","validatePropertyValue","propertyPath","validators","validator","validatorProblems","problem","existingProblems","get","nestedProblems","prependedProblems","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","element","elementPath","elementProblems","dataOrInstance","injectedPropertyNames","injectedPropertyOptions","propertyName","token","dependency","entityValidators","getEntityValidators","validatorMethod","delete","getRawInput","setRawInput","rawInput","protoValidators"],"mappings":"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"}
|