@rtpaulino/entity 0.24.2 → 0.25.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.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from './lib/entity.js';
3
3
  export * from './lib/entity-utils.js';
4
4
  export * from './lib/entity-di.js';
5
5
  export * from './lib/entity-registry.js';
6
+ export * from './lib/polymorphic-registry.js';
6
7
  export * from './lib/types.js';
7
8
  export * from './lib/property.js';
8
9
  export * from './lib/validation-error.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from './lib/entity.js';
3
3
  export * from './lib/entity-utils.js';
4
4
  export * from './lib/entity-di.js';
5
5
  export * from './lib/entity-registry.js';
6
+ export * from './lib/polymorphic-registry.js';
6
7
  export * from './lib/types.js';
7
8
  export * from './lib/property.js';
8
9
  export * from './lib/validation-error.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nexport * from './lib/entity.js';\nexport * from './lib/entity-utils.js';\nexport * from './lib/entity-di.js';\nexport * from './lib/entity-registry.js';\nexport * from './lib/types.js';\nexport * from './lib/property.js';\nexport * from './lib/validation-error.js';\nexport * from './lib/problem.js';\nexport * from './lib/validation-utils.js';\nexport * from './lib/primitive-deserializers.js';\nexport * from './lib/validators.js';\nexport * from './lib/zod-property.js';\nexport * from './lib/injected-property.js';\nexport * from './lib/entity-definition.js';\n"],"names":[],"mappings":"AAAA,OAAO,mBAAmB;AAE1B,cAAc,kBAAkB;AAChC,cAAc,wBAAwB;AACtC,cAAc,qBAAqB;AACnC,cAAc,2BAA2B;AACzC,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,mBAAmB;AACjC,cAAc,4BAA4B;AAC1C,cAAc,mCAAmC;AACjD,cAAc,sBAAsB;AACpC,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,6BAA6B"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nexport * from './lib/entity.js';\nexport * from './lib/entity-utils.js';\nexport * from './lib/entity-di.js';\nexport * from './lib/entity-registry.js';\nexport * from './lib/polymorphic-registry.js';\nexport * from './lib/types.js';\nexport * from './lib/property.js';\nexport * from './lib/validation-error.js';\nexport * from './lib/problem.js';\nexport * from './lib/validation-utils.js';\nexport * from './lib/primitive-deserializers.js';\nexport * from './lib/validators.js';\nexport * from './lib/zod-property.js';\nexport * from './lib/injected-property.js';\nexport * from './lib/entity-definition.js';\n"],"names":[],"mappings":"AAAA,OAAO,mBAAmB;AAE1B,cAAc,kBAAkB;AAChC,cAAc,wBAAwB;AACtC,cAAc,qBAAqB;AACnC,cAAc,2BAA2B;AACzC,cAAc,gCAAgC;AAC9C,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,mBAAmB;AACjC,cAAc,4BAA4B;AAC1C,cAAc,mCAAmC;AACjD,cAAc,sBAAsB;AACpC,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,6BAA6B"}
@@ -1 +1 @@
1
- {"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/lib/entity-utils.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import { prependArrayIndex, prependPropertyPath, createValidationError } from '.
8
8
  import { isPrimitiveConstructor, deserializePrimitive } from './primitive-deserializers.js';
9
9
  import { ok } from 'assert';
10
10
  import { EntityRegistry } from './entity-registry.js';
11
+ import { PolymorphicRegistry } from './polymorphic-registry.js';
11
12
  /**
12
13
  * WeakMap to store validation problems for entity instances
13
14
  */ const problemsStorage = new WeakMap();
@@ -427,6 +428,20 @@ export class EntityUtils {
427
428
  if (typeof plainObject !== 'object') {
428
429
  throw createValidationError(`Expects an object but received ${typeof plainObject}`);
429
430
  }
431
+ // Check for polymorphic base class - resolve to concrete variant if found
432
+ const discriminatorProperty = PolymorphicRegistry.getDiscriminatorProperty(entityClass);
433
+ if (discriminatorProperty) {
434
+ const discriminatorValue = plainObject[discriminatorProperty];
435
+ if (discriminatorValue === undefined) {
436
+ throw createValidationError(`Missing polymorphic discriminator property '${discriminatorProperty}' ` + `for base class '${entityClass.name}'. ` + `The discriminator property is required to determine the correct variant class.`);
437
+ }
438
+ const variantClass = PolymorphicRegistry.getVariant(entityClass, discriminatorValue);
439
+ if (!variantClass) {
440
+ throw createValidationError(`Unknown polymorphic variant '${String(discriminatorValue)}' ` + `for base class '${entityClass.name}'. ` + `Discriminator property: '${discriminatorProperty}'. ` + `Ensure the variant class is decorated with @PolymorphicVariant.`);
441
+ }
442
+ // Recursively parse as the concrete variant class
443
+ return this._parseInternal(variantClass, plainObject, options);
444
+ }
430
445
  const strict = options.strict ?? false;
431
446
  const skipDefaults = options.skipDefaults ?? false;
432
447
  const skipMissing = options.skipMissing ?? false;
@@ -491,7 +506,8 @@ export class EntityUtils {
491
506
  }
492
507
  return {
493
508
  data,
494
- hardProblems
509
+ hardProblems,
510
+ entityClass
495
511
  };
496
512
  }
497
513
  /**
@@ -539,14 +555,14 @@ export class EntityUtils {
539
555
  * ```
540
556
  */ static async parse(entityClass, plainObject, parseOptions = {}) {
541
557
  const strict = parseOptions?.strict ?? false;
542
- const { data, hardProblems } = await this._parseInternal(entityClass, plainObject, {
558
+ const { data, hardProblems, entityClass: resolvedEntityClass } = await this._parseInternal(entityClass, plainObject, {
543
559
  strict
544
560
  });
545
561
  if (hardProblems.length > 0) {
546
562
  throw new ValidationError(hardProblems);
547
563
  }
548
- await this.addInjectedDependencies(data, entityClass.prototype);
549
- const instance = new entityClass(data);
564
+ await this.addInjectedDependencies(data, resolvedEntityClass.prototype);
565
+ const instance = new resolvedEntityClass(data);
550
566
  rawInputStorage.set(instance, plainObject);
551
567
  const problems = await this.validate(instance);
552
568
  if (problems.length > 0 && strict) {
@@ -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 prependArrayIndex,\n prependPropertyPath,\n createValidationError,\n} from './validation-utils.js';\nimport {\n isPrimitiveConstructor,\n deserializePrimitive,\n} from './primitive-deserializers.js';\nimport { ok } from 'assert';\nimport { EntityRegistry } from './entity-registry.js';\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 * Gets the registered name for an entity class or instance\n *\n * @param entityOrClass - The entity class constructor or instance\n * @returns The entity name, or undefined if not found\n *\n * @example\n * ```typescript\n * @Entity({ name: 'CustomUser' })\n * class User {\n * name: string;\n * }\n *\n * console.log(EntityUtils.getEntityName(User)); // 'CustomUser'\n * console.log(EntityUtils.getEntityName(new User())); // 'CustomUser'\n * ```\n */\n static getEntityName(entityOrClass: unknown): string | undefined {\n if (!this.isEntity(entityOrClass)) {\n return undefined;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n return options.name;\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 /**\n * Checks if a given entity is marked as a stringifiable entity\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns true if the entity is a stringifiable entity, false otherwise\n *\n * @example\n * ```typescript\n * @Stringifiable()\n * class UserId {\n * @StringProperty()\n * value: string;\n * }\n *\n * const userId = new UserId({ value: 'user-123' });\n * console.log(EntityUtils.isStringifiable(userId)); // true\n * console.log(EntityUtils.isStringifiable(UserId)); // true\n * ```\n */\n static isStringifiable(entityOrClass: unknown): boolean {\n if (!this.isEntity(entityOrClass)) {\n return false;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n\n return options.stringifiable === true;\n }\n\n /**\n * Gets the \"wrapper\" property name for entities that act as transparent wrappers.\n * When set, this property name is excluded from error paths during validation.\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns The wrapper property name, or undefined if not a wrapper entity\n * @private\n */\n private static getWrapperPropertyName(\n entityOrClass: unknown,\n ): string | undefined {\n if (!this.isEntity(entityOrClass)) {\n return undefined;\n }\n return this.getEntityOptions(entityOrClass).wrapperProperty;\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.isStringifiable(entity)) {\n const valuePropertyOptions = this.getPropertyOptions(entity, 'value');\n if (!valuePropertyOptions) {\n throw new Error(\n `Stringifiable entity 'value' property is missing metadata`,\n );\n }\n if (valuePropertyOptions.array) {\n throw new Error(\n `Stringifiable entity 'value' property must not be an array`,\n );\n }\n if (valuePropertyOptions.type?.() !== String) {\n throw new Error(\n `Stringifiable entity 'value' property must be of type String`,\n );\n }\n\n return this.serializeValue((entity as any).value, valuePropertyOptions);\n }\n\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, options));\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 const serialized = this.toJSON(value);\n\n // If this is a discriminated entity property, add the discriminator inline\n if (options?.discriminated === true) {\n const discriminatorProperty = options.discriminatorProperty;\n ok(discriminatorProperty, 'Discriminator property must be defined');\n\n const entityClass = Object.getPrototypeOf(value).constructor;\n const entityName = this.getEntityName(entityClass);\n\n if (!entityName) {\n throw new Error(\n `Cannot serialize discriminated entity: Entity class '${entityClass.name}' is not registered. Ensure it's decorated with @Entity().`,\n );\n }\n\n if (\n typeof serialized !== 'object' ||\n Array.isArray(serialized) ||\n serialized === null\n ) {\n throw new Error(\n `Cannot serialize discriminated entity: Expected serialized value to be an object.`,\n );\n }\n\n return {\n ...serialized,\n [discriminatorProperty]: entityName,\n } as Record<string, unknown>;\n }\n\n return serialized;\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 const wrapperPropertyName = this.getWrapperPropertyName(entityClass);\n\n if (wrapperPropertyName) {\n plainObject = { [wrapperPropertyName]: 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 isWrapperProperty = wrapperPropertyName === key;\n if (isWrapperProperty) {\n hardProblems.push(...error.problems);\n } else {\n const problems = prependPropertyPath(key, error.problems);\n hardProblems.push(...problems);\n }\n } else if (error instanceof Error) {\n hardProblems.push(\n new Problem({\n property: wrapperPropertyName === key ? '' : 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 const isArray = options.array === true;\n const isSparse = options.sparse === true;\n const isDiscriminated = options.discriminated === 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 if (isDiscriminated) {\n result.push(\n await this.deserializeDiscriminatedValue(item, options),\n );\n } else {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\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 if (isDiscriminated) {\n return await this.deserializeDiscriminatedValue(value, options);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\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 * Deserializes a discriminated entity value by reading the discriminator and looking up the entity class\n * @private\n */\n private static async deserializeDiscriminatedValue(\n value: unknown,\n options: PropertyOptions,\n ): Promise<unknown> {\n if (value == null) {\n throw createValidationError(\n `Cannot deserialize discriminated entity from null or undefined`,\n );\n }\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n throw createValidationError(\n `Discriminated entity must be an object, received ${typeof value}`,\n );\n }\n\n const discriminatorProperty = options.discriminatorProperty;\n ok(discriminatorProperty, 'Discriminator property must be defined');\n\n const discriminatorValue = (value as Record<string, unknown>)[\n discriminatorProperty\n ];\n\n if (\n typeof discriminatorValue !== 'string' ||\n discriminatorValue.trim() === ''\n ) {\n throw createValidationError(\n `Missing or invalid discriminator property '${discriminatorProperty}'. Expected a non-empty string.`,\n );\n }\n\n const entityClass = EntityRegistry.get(discriminatorValue);\n\n if (!entityClass) {\n throw createValidationError(\n `Unknown entity type '${discriminatorValue}'. No entity registered with this name.`,\n );\n }\n\n return await this.parse(\n entityClass as new (data: any) => object,\n value as Record<string, unknown>,\n {},\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 if (validatorProblems.length > 0) {\n const prepended = prependPropertyPath(\n propertyPath,\n validatorProblems,\n );\n problems.push(...prepended);\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 if (nestedProblems.length > 0) {\n const prepended = prependPropertyPath(propertyPath, nestedProblems);\n problems.push(...prepended);\n }\n }\n\n return problems;\n }\n\n /**\n * Checks if an array contains any entity elements\n * @private\n */\n private static hasEntityElements(value: unknown): boolean {\n if (!Array.isArray(value)) {\n return false;\n }\n return value.some((element) => this.isEntity(element));\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 if (validatorProblems.length > 0) {\n const prepended = prependPropertyPath(key, validatorProblems);\n problems.push(...prepended);\n }\n }\n\n const validators = options.validators || [];\n if (validators.length > 0 || this.hasEntityElements(value)) {\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 const wrapperProperty = this.getWrapperPropertyName(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 propertyPath = wrapperProperty === key ? '' : key;\n const validationProblems = await this.runPropertyValidators(\n propertyPath,\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","prependArrayIndex","prependPropertyPath","createValidationError","isPrimitiveConstructor","deserializePrimitive","ok","EntityRegistry","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","getEntityOptions","entityOrClass","options","getMetadata","getEntityName","undefined","name","isCollectionEntity","collection","isStringifiable","stringifiable","getWrapperPropertyName","wrapperProperty","sameEntity","a","b","getPropertyKeys","target","currentProto","prototype","keys","seen","Set","protoKeys","getOwnMetadata","key","has","add","push","getPropertyOptions","propertyKey","protoOptions","equals","val1","val2","diff","length","oldEntity","newEntity","Error","diffs","oldValue","newValue","propertyOptions","areEqual","property","changes","reduce","acc","toJSON","entity","valuePropertyOptions","array","type","String","serializeValue","value","collectionPropertyOptions","result","passthrough","serialize","map","item","Date","toISOString","toString","serialized","discriminated","discriminatorProperty","entityClass","entityName","_parseInternal","plainObject","wrapperPropertyName","strict","skipDefaults","skipMissing","data","hardProblems","message","isOptional","optional","valueToSet","default","deserializeValue","error","isWrapperProperty","problems","parse","parseOptions","addInjectedDependencies","instance","set","validate","safeParse","getProblems","success","partialParse","safePartialParse","propertyProblems","validateProperties","validationProblems","setProblems","update","updates","Constructor","preventUpdates","newInstance","safeUpdate","updatedInstance","isSparse","sparse","isDiscriminated","arrayProblems","index","deserialize","deserializeDiscriminatedValue","typeConstructor","deserializeSingleValue","discriminatorValue","trim","get","validatePropertyValue","propertyPath","validators","validator","validatorProblems","prepended","existingProblems","nestedProblems","hasEntityElements","some","element","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","elementPath","elementProblems","dataOrInstance","injectedPropertyNames","injectedPropertyOptions","propertyName","token","dependency","entityValidators","getEntityValidators","validatorMethod","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 prependArrayIndex,\n prependPropertyPath,\n createValidationError,\n} from './validation-utils.js';\nimport {\n isPrimitiveConstructor,\n deserializePrimitive,\n} from './primitive-deserializers.js';\nimport { ok } from 'assert';\nimport { EntityRegistry } from './entity-registry.js';\nimport { PolymorphicRegistry } from './polymorphic-registry.js';\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 * Gets the registered name for an entity class or instance\n *\n * @param entityOrClass - The entity class constructor or instance\n * @returns The entity name, or undefined if not found\n *\n * @example\n * ```typescript\n * @Entity({ name: 'CustomUser' })\n * class User {\n * name: string;\n * }\n *\n * console.log(EntityUtils.getEntityName(User)); // 'CustomUser'\n * console.log(EntityUtils.getEntityName(new User())); // 'CustomUser'\n * ```\n */\n static getEntityName(entityOrClass: unknown): string | undefined {\n if (!this.isEntity(entityOrClass)) {\n return undefined;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n return options.name;\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 /**\n * Checks if a given entity is marked as a stringifiable entity\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns true if the entity is a stringifiable entity, false otherwise\n *\n * @example\n * ```typescript\n * @Stringifiable()\n * class UserId {\n * @StringProperty()\n * value: string;\n * }\n *\n * const userId = new UserId({ value: 'user-123' });\n * console.log(EntityUtils.isStringifiable(userId)); // true\n * console.log(EntityUtils.isStringifiable(UserId)); // true\n * ```\n */\n static isStringifiable(entityOrClass: unknown): boolean {\n if (!this.isEntity(entityOrClass)) {\n return false;\n }\n\n const options = this.getEntityOptions(entityOrClass);\n\n return options.stringifiable === true;\n }\n\n /**\n * Gets the \"wrapper\" property name for entities that act as transparent wrappers.\n * When set, this property name is excluded from error paths during validation.\n *\n * @param entityOrClass - The entity instance or class to check\n * @returns The wrapper property name, or undefined if not a wrapper entity\n * @private\n */\n private static getWrapperPropertyName(\n entityOrClass: unknown,\n ): string | undefined {\n if (!this.isEntity(entityOrClass)) {\n return undefined;\n }\n return this.getEntityOptions(entityOrClass).wrapperProperty;\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.isStringifiable(entity)) {\n const valuePropertyOptions = this.getPropertyOptions(entity, 'value');\n if (!valuePropertyOptions) {\n throw new Error(\n `Stringifiable entity 'value' property is missing metadata`,\n );\n }\n if (valuePropertyOptions.array) {\n throw new Error(\n `Stringifiable entity 'value' property must not be an array`,\n );\n }\n if (valuePropertyOptions.type?.() !== String) {\n throw new Error(\n `Stringifiable entity 'value' property must be of type String`,\n );\n }\n\n return this.serializeValue((entity as any).value, valuePropertyOptions);\n }\n\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, options));\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 const serialized = this.toJSON(value);\n\n // If this is a discriminated entity property, add the discriminator inline\n if (options?.discriminated === true) {\n const discriminatorProperty = options.discriminatorProperty;\n ok(discriminatorProperty, 'Discriminator property must be defined');\n\n const entityClass = Object.getPrototypeOf(value).constructor;\n const entityName = this.getEntityName(entityClass);\n\n if (!entityName) {\n throw new Error(\n `Cannot serialize discriminated entity: Entity class '${entityClass.name}' is not registered. Ensure it's decorated with @Entity().`,\n );\n }\n\n if (\n typeof serialized !== 'object' ||\n Array.isArray(serialized) ||\n serialized === null\n ) {\n throw new Error(\n `Cannot serialize discriminated entity: Expected serialized value to be an object.`,\n );\n }\n\n return {\n ...serialized,\n [discriminatorProperty]: entityName,\n } as Record<string, unknown>;\n }\n\n return serialized;\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<{\n data: Record<string, unknown>;\n hardProblems: Problem[];\n entityClass: new (data: any) => T;\n }> {\n const wrapperPropertyName = this.getWrapperPropertyName(entityClass);\n\n if (wrapperPropertyName) {\n plainObject = { [wrapperPropertyName]: 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 // Check for polymorphic base class - resolve to concrete variant if found\n const discriminatorProperty =\n PolymorphicRegistry.getDiscriminatorProperty(entityClass);\n\n if (discriminatorProperty) {\n const discriminatorValue = (plainObject as Record<string, unknown>)[\n discriminatorProperty\n ];\n\n if (discriminatorValue === undefined) {\n throw createValidationError(\n `Missing polymorphic discriminator property '${discriminatorProperty}' ` +\n `for base class '${entityClass.name}'. ` +\n `The discriminator property is required to determine the correct variant class.`,\n );\n }\n\n const variantClass = PolymorphicRegistry.getVariant(\n entityClass,\n discriminatorValue,\n );\n\n if (!variantClass) {\n throw createValidationError(\n `Unknown polymorphic variant '${String(discriminatorValue)}' ` +\n `for base class '${entityClass.name}'. ` +\n `Discriminator property: '${discriminatorProperty}'. ` +\n `Ensure the variant class is decorated with @PolymorphicVariant.`,\n );\n }\n\n // Recursively parse as the concrete variant class\n return this._parseInternal(\n variantClass as new (data: any) => T,\n plainObject,\n options,\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 isWrapperProperty = wrapperPropertyName === key;\n if (isWrapperProperty) {\n hardProblems.push(...error.problems);\n } else {\n const problems = prependPropertyPath(key, error.problems);\n hardProblems.push(...problems);\n }\n } else if (error instanceof Error) {\n hardProblems.push(\n new Problem({\n property: wrapperPropertyName === key ? '' : key,\n message: error.message,\n }),\n );\n } else {\n throw error;\n }\n }\n }\n\n return { data, hardProblems, entityClass };\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 {\n data,\n hardProblems,\n entityClass: resolvedEntityClass,\n } = await this._parseInternal(entityClass, plainObject, { strict });\n\n if (hardProblems.length > 0) {\n throw new ValidationError(hardProblems);\n }\n\n await this.addInjectedDependencies(data, resolvedEntityClass.prototype);\n\n const instance = new resolvedEntityClass(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 const isArray = options.array === true;\n const isSparse = options.sparse === true;\n const isDiscriminated = options.discriminated === 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 if (isDiscriminated) {\n result.push(\n await this.deserializeDiscriminatedValue(item, options),\n );\n } else {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\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 if (isDiscriminated) {\n return await this.deserializeDiscriminatedValue(value, options);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const typeConstructor = options.type!();\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 * Deserializes a discriminated entity value by reading the discriminator and looking up the entity class\n * @private\n */\n private static async deserializeDiscriminatedValue(\n value: unknown,\n options: PropertyOptions,\n ): Promise<unknown> {\n if (value == null) {\n throw createValidationError(\n `Cannot deserialize discriminated entity from null or undefined`,\n );\n }\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n throw createValidationError(\n `Discriminated entity must be an object, received ${typeof value}`,\n );\n }\n\n const discriminatorProperty = options.discriminatorProperty;\n ok(discriminatorProperty, 'Discriminator property must be defined');\n\n const discriminatorValue = (value as Record<string, unknown>)[\n discriminatorProperty\n ];\n\n if (\n typeof discriminatorValue !== 'string' ||\n discriminatorValue.trim() === ''\n ) {\n throw createValidationError(\n `Missing or invalid discriminator property '${discriminatorProperty}'. Expected a non-empty string.`,\n );\n }\n\n const entityClass = EntityRegistry.get(discriminatorValue);\n\n if (!entityClass) {\n throw createValidationError(\n `Unknown entity type '${discriminatorValue}'. No entity registered with this name.`,\n );\n }\n\n return await this.parse(\n entityClass as new (data: any) => object,\n value as Record<string, unknown>,\n {},\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 if (validatorProblems.length > 0) {\n const prepended = prependPropertyPath(\n propertyPath,\n validatorProblems,\n );\n problems.push(...prepended);\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 if (nestedProblems.length > 0) {\n const prepended = prependPropertyPath(propertyPath, nestedProblems);\n problems.push(...prepended);\n }\n }\n\n return problems;\n }\n\n /**\n * Checks if an array contains any entity elements\n * @private\n */\n private static hasEntityElements(value: unknown): boolean {\n if (!Array.isArray(value)) {\n return false;\n }\n return value.some((element) => this.isEntity(element));\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 if (validatorProblems.length > 0) {\n const prepended = prependPropertyPath(key, validatorProblems);\n problems.push(...prepended);\n }\n }\n\n const validators = options.validators || [];\n if (validators.length > 0 || this.hasEntityElements(value)) {\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 const wrapperProperty = this.getWrapperPropertyName(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 propertyPath = wrapperProperty === key ? '' : key;\n const validationProblems = await this.runPropertyValidators(\n propertyPath,\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","prependArrayIndex","prependPropertyPath","createValidationError","isPrimitiveConstructor","deserializePrimitive","ok","EntityRegistry","PolymorphicRegistry","problemsStorage","WeakMap","rawInputStorage","EntityUtils","isEntity","obj","Reflect","hasMetadata","Array","isArray","constructor","Object","getPrototypeOf","getEntityOptions","entityOrClass","options","getMetadata","getEntityName","undefined","name","isCollectionEntity","collection","isStringifiable","stringifiable","getWrapperPropertyName","wrapperProperty","sameEntity","a","b","getPropertyKeys","target","currentProto","prototype","keys","seen","Set","protoKeys","getOwnMetadata","key","has","add","push","getPropertyOptions","propertyKey","protoOptions","equals","val1","val2","diff","length","oldEntity","newEntity","Error","diffs","oldValue","newValue","propertyOptions","areEqual","property","changes","reduce","acc","toJSON","entity","valuePropertyOptions","array","type","String","serializeValue","value","collectionPropertyOptions","result","passthrough","serialize","map","item","Date","toISOString","toString","serialized","discriminated","discriminatorProperty","entityClass","entityName","_parseInternal","plainObject","wrapperPropertyName","getDiscriminatorProperty","discriminatorValue","variantClass","getVariant","strict","skipDefaults","skipMissing","data","hardProblems","message","isOptional","optional","valueToSet","default","deserializeValue","error","isWrapperProperty","problems","parse","parseOptions","resolvedEntityClass","addInjectedDependencies","instance","set","validate","safeParse","getProblems","success","partialParse","safePartialParse","propertyProblems","validateProperties","validationProblems","setProblems","update","updates","Constructor","preventUpdates","newInstance","safeUpdate","updatedInstance","isSparse","sparse","isDiscriminated","arrayProblems","index","deserialize","deserializeDiscriminatedValue","typeConstructor","deserializeSingleValue","trim","get","validatePropertyValue","propertyPath","validators","validator","validatorProblems","prepended","existingProblems","nestedProblems","hasEntityElements","some","element","runPropertyValidators","isPassthrough","valueProblems","arrayValidators","i","elementPath","elementProblems","dataOrInstance","injectedPropertyNames","injectedPropertyOptions","propertyName","token","dependency","entityValidators","getEntityValidators","validatorMethod","delete","getRawInput","setRawInput","rawInput","protoValidators"],"mappings":"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"}
@@ -164,4 +164,64 @@ export declare function Stringifiable(options?: Pick<EntityOptions, 'name'>): Cl
164
164
  * ```
165
165
  */
166
166
  export declare function EntityValidator(): MethodDecorator;
167
+ /**
168
+ * Decorator that registers a class as a polymorphic variant of a base class.
169
+ *
170
+ * Used for class hierarchies where an abstract base class has multiple concrete implementations,
171
+ * and a discriminator property determines which variant to instantiate during parsing.
172
+ *
173
+ * @param baseClass - The base class this variant extends (must have a @PolymorphicProperty)
174
+ * @param discriminatorValue - The value of the discriminator property that identifies this variant
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * enum SchemaPropertyType {
179
+ * STRING = 'string',
180
+ * NUMBER = 'number',
181
+ * }
182
+ *
183
+ * @Entity()
184
+ * abstract class SchemaProperty {
185
+ * @StringProperty({ minLength: 1 })
186
+ * name!: string;
187
+ *
188
+ * @PolymorphicProperty(SchemaPropertyType)
189
+ * type!: SchemaPropertyType;
190
+ * }
191
+ *
192
+ * @Entity()
193
+ * @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
194
+ * class StringSchemaProperty extends SchemaProperty {
195
+ * readonly type = SchemaPropertyType.STRING;
196
+ *
197
+ * @IntProperty({ optional: true })
198
+ * minLength?: number;
199
+ *
200
+ * constructor(data: { name: string; minLength?: number }) {
201
+ * super({ ...data, type: SchemaPropertyType.STRING });
202
+ * this.minLength = data.minLength;
203
+ * }
204
+ * }
205
+ *
206
+ * @Entity()
207
+ * @PolymorphicVariant(SchemaProperty, SchemaPropertyType.NUMBER)
208
+ * class NumberSchemaProperty extends SchemaProperty {
209
+ * readonly type = SchemaPropertyType.NUMBER;
210
+ *
211
+ * @NumberProperty({ optional: true })
212
+ * min?: number;
213
+ *
214
+ * constructor(data: { name: string; min?: number }) {
215
+ * super({ ...data, type: SchemaPropertyType.NUMBER });
216
+ * this.min = data.min;
217
+ * }
218
+ * }
219
+ *
220
+ * // Parsing automatically selects the correct variant based on 'type'
221
+ * const data = { name: 'age', type: 'number', min: 0 };
222
+ * const prop = await EntityUtils.parse(SchemaProperty, data);
223
+ * // prop is NumberSchemaProperty instance
224
+ * ```
225
+ */
226
+ export declare function PolymorphicVariant<T extends Function>(baseClass: T, discriminatorValue: unknown): ClassDecorator;
167
227
  //# sourceMappingURL=entity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/lib/entity.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,cAAc,CAwBlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAMhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAmBjD"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/lib/entity.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,cAAc,CAwBlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAMhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAmBjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,QAAQ,EACnD,SAAS,EAAE,CAAC,EACZ,kBAAkB,EAAE,OAAO,GAC1B,cAAc,CAahB"}