@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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/entity-utils.d.ts.map +1 -1
- package/dist/lib/entity-utils.js +20 -4
- package/dist/lib/entity-utils.js.map +1 -1
- package/dist/lib/entity.d.ts +60 -0
- package/dist/lib/entity.d.ts.map +1 -1
- package/dist/lib/entity.js +72 -1
- package/dist/lib/entity.js.map +1 -1
- package/dist/lib/polymorphic-registry.d.ts +57 -0
- package/dist/lib/polymorphic-registry.d.ts.map +1 -0
- package/dist/lib/polymorphic-registry.js +83 -0
- package/dist/lib/polymorphic-registry.js.map +1 -0
- package/dist/lib/property.d.ts +45 -0
- package/dist/lib/property.d.ts.map +1 -1
- package/dist/lib/property.js +76 -1
- package/dist/lib/property.js.map +1 -1
- package/dist/lib/types.d.ts +25 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +6 -0
- package/dist/lib/types.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/entity.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ENTITY_METADATA_KEY, ENTITY_OPTIONS_METADATA_KEY, ENTITY_VALIDATOR_METADATA_KEY } from './types.js';
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-function-type */ import { ENTITY_METADATA_KEY, ENTITY_OPTIONS_METADATA_KEY, ENTITY_VALIDATOR_METADATA_KEY, POLYMORPHIC_VARIANT_METADATA_KEY } from './types.js';
|
|
2
2
|
import { EntityRegistry } from './entity-registry.js';
|
|
3
|
+
import { PolymorphicRegistry } from './polymorphic-registry.js';
|
|
3
4
|
/**
|
|
4
5
|
* Decorator that marks a class as an Entity.
|
|
5
6
|
* This allows us to identify entity instances later.
|
|
@@ -167,5 +168,75 @@ import { EntityRegistry } from './entity-registry.js';
|
|
|
167
168
|
Reflect.defineMetadata(ENTITY_VALIDATOR_METADATA_KEY, existingValidators, target);
|
|
168
169
|
};
|
|
169
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Decorator that registers a class as a polymorphic variant of a base class.
|
|
173
|
+
*
|
|
174
|
+
* Used for class hierarchies where an abstract base class has multiple concrete implementations,
|
|
175
|
+
* and a discriminator property determines which variant to instantiate during parsing.
|
|
176
|
+
*
|
|
177
|
+
* @param baseClass - The base class this variant extends (must have a @PolymorphicProperty)
|
|
178
|
+
* @param discriminatorValue - The value of the discriminator property that identifies this variant
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* enum SchemaPropertyType {
|
|
183
|
+
* STRING = 'string',
|
|
184
|
+
* NUMBER = 'number',
|
|
185
|
+
* }
|
|
186
|
+
*
|
|
187
|
+
* @Entity()
|
|
188
|
+
* abstract class SchemaProperty {
|
|
189
|
+
* @StringProperty({ minLength: 1 })
|
|
190
|
+
* name!: string;
|
|
191
|
+
*
|
|
192
|
+
* @PolymorphicProperty(SchemaPropertyType)
|
|
193
|
+
* type!: SchemaPropertyType;
|
|
194
|
+
* }
|
|
195
|
+
*
|
|
196
|
+
* @Entity()
|
|
197
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
|
|
198
|
+
* class StringSchemaProperty extends SchemaProperty {
|
|
199
|
+
* readonly type = SchemaPropertyType.STRING;
|
|
200
|
+
*
|
|
201
|
+
* @IntProperty({ optional: true })
|
|
202
|
+
* minLength?: number;
|
|
203
|
+
*
|
|
204
|
+
* constructor(data: { name: string; minLength?: number }) {
|
|
205
|
+
* super({ ...data, type: SchemaPropertyType.STRING });
|
|
206
|
+
* this.minLength = data.minLength;
|
|
207
|
+
* }
|
|
208
|
+
* }
|
|
209
|
+
*
|
|
210
|
+
* @Entity()
|
|
211
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.NUMBER)
|
|
212
|
+
* class NumberSchemaProperty extends SchemaProperty {
|
|
213
|
+
* readonly type = SchemaPropertyType.NUMBER;
|
|
214
|
+
*
|
|
215
|
+
* @NumberProperty({ optional: true })
|
|
216
|
+
* min?: number;
|
|
217
|
+
*
|
|
218
|
+
* constructor(data: { name: string; min?: number }) {
|
|
219
|
+
* super({ ...data, type: SchemaPropertyType.NUMBER });
|
|
220
|
+
* this.min = data.min;
|
|
221
|
+
* }
|
|
222
|
+
* }
|
|
223
|
+
*
|
|
224
|
+
* // Parsing automatically selects the correct variant based on 'type'
|
|
225
|
+
* const data = { name: 'age', type: 'number', min: 0 };
|
|
226
|
+
* const prop = await EntityUtils.parse(SchemaProperty, data);
|
|
227
|
+
* // prop is NumberSchemaProperty instance
|
|
228
|
+
* ```
|
|
229
|
+
*/ export function PolymorphicVariant(baseClass, discriminatorValue) {
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
231
|
+
return function(target) {
|
|
232
|
+
// Register the variant in the registry
|
|
233
|
+
PolymorphicRegistry.registerVariant(baseClass, discriminatorValue, target);
|
|
234
|
+
// Store metadata on the class for introspection
|
|
235
|
+
Reflect.defineMetadata(POLYMORPHIC_VARIANT_METADATA_KEY, {
|
|
236
|
+
baseClass,
|
|
237
|
+
discriminatorValue
|
|
238
|
+
}, target);
|
|
239
|
+
};
|
|
240
|
+
}
|
|
170
241
|
|
|
171
242
|
//# sourceMappingURL=entity.js.map
|
package/dist/lib/entity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/entity.ts"],"sourcesContent":["import {\n ENTITY_METADATA_KEY,\n ENTITY_OPTIONS_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n} from './types.js';\nimport { EntityRegistry } from './entity-registry.js';\n\n/**\n * Options for Entity decorator\n */\nexport interface EntityOptions {\n /**\n * Optional name for the entity. Used for discriminated entity deserialization.\n * If not specified, the class name will be used.\n * Must be unique across all entities - conflicts will throw an error.\n */\n name?: string;\n /**\n * Whether this entity represents a collection.\n * Collection entities must have a 'collection' property that is an array.\n * When serialized, collection entities are unwrapped to just their array.\n * When deserialized from an array, the array is wrapped in { collection: [...] }.\n */\n collection?: boolean;\n /**\n * Whether this entity represents a stringifiable value.\n * Stringifiable classes must have a 'value' property that is a string.\n * When serialized, stringifiable instances are unwrapped to just their string.\n * When deserialized from a string, the string is wrapped in { value: \"...\" }.\n */\n stringifiable?: boolean;\n /**\n * The name of the single \"wrapper\" property for entities that act as transparent wrappers.\n * When set, this property name is excluded from error paths during validation.\n * Used by @CollectionEntity ('collection') and @Stringifiable ('value').\n */\n wrapperProperty?: string;\n /**\n * Whether to register this entity in the EntityRegistry.\n * Set to false for dynamic entities to prevent memory leaks.\n * Defaults to true.\n */\n register?: boolean;\n}\n\n/**\n * Decorator that marks a class as an Entity.\n * This allows us to identify entity instances later.\n *\n * @param options - Optional configuration for the entity\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * name: string;\n * }\n *\n * @Entity({ name: 'CustomUser' })\n * class User {\n * name: string;\n * }\n *\n * @Entity({ collection: true })\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n * ```\n */\nexport function Entity(options: EntityOptions = {}): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return function (target: Function) {\n // Store metadata on the class constructor\n Reflect.defineMetadata(ENTITY_METADATA_KEY, true, target);\n\n // Determine the entity name - use provided name or fall back to class name\n const entityName = options.name ?? target.name;\n\n // Register the entity in the global registry (unless explicitly disabled)\n const shouldRegister = options.register !== false;\n if (shouldRegister) {\n EntityRegistry.register(entityName, target);\n }\n\n // Store the name in options for later retrieval\n const optionsWithName = { ...options, name: entityName };\n\n Reflect.defineMetadata(\n ENTITY_OPTIONS_METADATA_KEY,\n optionsWithName,\n target,\n );\n };\n}\n\n/**\n * Decorator that marks a class as a Collection Entity.\n * This is syntax sugar for @Entity({ collection: true }).\n *\n * Collection entities must have a 'collection' property that is an array.\n * When serialized with EntityUtils.toJSON(), they are unwrapped to just the array.\n * When deserialized from an array, the array is wrapped in { collection: [...] }.\n *\n * @example\n * ```typescript\n * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * readonly collection: string[];\n *\n * constructor(data: { collection: string[] }) {\n * this.collection = data.collection;\n * }\n * }\n *\n * @Entity()\n * class Article {\n * @EntityProperty(() => Tags)\n * tags!: Tags;\n * }\n *\n * const article = new Article(...);\n * const json = EntityUtils.toJSON(article);\n * // { tags: [\"tag1\", \"tag2\"] } - unwrapped to array\n *\n * // Also works when serializing the collection directly:\n * const tagsJson = EntityUtils.toJSON(tags);\n * // [\"tag1\", \"tag2\"] - unwrapped to array\n * ```\n */\nexport function CollectionEntity(\n options: Pick<EntityOptions, 'name'> = {},\n): ClassDecorator {\n return Entity({\n collection: true,\n wrapperProperty: 'collection',\n ...options,\n });\n}\n\n/**\n * Decorator that marks a class as Stringifiable.\n * This is syntax sugar for @Entity({ stringifiable: true }).\n *\n * Stringifiable classes must have a 'value' property that is a string.\n * When serialized with EntityUtils.toJSON(), they are unwrapped to just the string.\n * When deserialized from a string, the string is wrapped in { value: \"...\" }.\n *\n * @example\n * ```typescript\n * @Stringifiable()\n * class UserId {\n * @StringProperty()\n * readonly value: string;\n *\n * constructor(data: { value: string }) {\n * this.value = data.value;\n * }\n * }\n *\n * @Entity()\n * class User {\n * @EntityProperty(() => UserId)\n * id!: UserId;\n * }\n *\n * const user = new User(...);\n * const json = EntityUtils.toJSON(user);\n * // { id: \"user-123\" } - unwrapped to string\n *\n * // Also works when serializing the stringifiable directly:\n * const userId = new UserId({ value: \"user-123\" });\n * const idJson = EntityUtils.toJSON(userId);\n * // \"user-123\" - unwrapped to string\n *\n * // Parse from string:\n * const parsed = await EntityUtils.parse(UserId, \"user-456\");\n * // UserId { value: \"user-456\" }\n * ```\n */\nexport function Stringifiable(\n options: Pick<EntityOptions, 'name'> = {},\n): ClassDecorator {\n return Entity({ stringifiable: true, wrapperProperty: 'value', ...options });\n}\n\n/**\n * Decorator that marks a method as an entity validator.\n * The method should return an array of Problems.\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) firstName!: string;\n * @Property({ type: () => String }) lastName!: string;\n *\n * @EntityValidator()\n * validateNames(): Problem[] {\n * const problems: Problem[] = [];\n * if (this.firstName === this.lastName) {\n * problems.push(new Problem({\n * property: 'firstName',\n * message: 'First and last name cannot be the same'\n * }));\n * }\n * return problems;\n * }\n * }\n * ```\n */\nexport function EntityValidator(): MethodDecorator {\n return (target: object, propertyKey: string | symbol): void => {\n if (typeof propertyKey !== 'string') {\n return;\n }\n\n const existingValidators: string[] =\n Reflect.getOwnMetadata(ENTITY_VALIDATOR_METADATA_KEY, target) || [];\n\n if (!existingValidators.includes(propertyKey)) {\n existingValidators.push(propertyKey);\n }\n\n Reflect.defineMetadata(\n ENTITY_VALIDATOR_METADATA_KEY,\n existingValidators,\n target,\n );\n };\n}\n"],"names":["ENTITY_METADATA_KEY","ENTITY_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","EntityRegistry","Entity","options","target","Reflect","defineMetadata","entityName","name","shouldRegister","register","optionsWithName","CollectionEntity","collection","wrapperProperty","Stringifiable","stringifiable","EntityValidator","propertyKey","existingValidators","getOwnMetadata","includes","push"],"mappings":"AAAA,SACEA,mBAAmB,EACnBC,2BAA2B,EAC3BC,6BAA6B,QACxB,aAAa;AACpB,SAASC,cAAc,QAAQ,uBAAuB;AAwCtD;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,OAAOC,UAAyB,CAAC,CAAC;IAChD,sEAAsE;IACtE,OAAO,SAAUC,MAAgB;QAC/B,0CAA0C;QAC1CC,QAAQC,cAAc,CAACR,qBAAqB,MAAMM;QAElD,2EAA2E;QAC3E,MAAMG,aAAaJ,QAAQK,IAAI,IAAIJ,OAAOI,IAAI;QAE9C,0EAA0E;QAC1E,MAAMC,iBAAiBN,QAAQO,QAAQ,KAAK;QAC5C,IAAID,gBAAgB;YAClBR,eAAeS,QAAQ,CAACH,YAAYH;QACtC;QAEA,gDAAgD;QAChD,MAAMO,kBAAkB;YAAE,GAAGR,OAAO;YAAEK,MAAMD;QAAW;QAEvDF,QAAQC,cAAc,CACpBP,6BACAY,iBACAP;IAEJ;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCC,GACD,OAAO,SAASQ,iBACdT,UAAuC,CAAC,CAAC;IAEzC,OAAOD,OAAO;QACZW,YAAY;QACZC,iBAAiB;QACjB,GAAGX,OAAO;IACZ;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCC,GACD,OAAO,SAASY,cACdZ,UAAuC,CAAC,CAAC;IAEzC,OAAOD,OAAO;QAAEc,eAAe;QAAMF,iBAAiB;QAAS,GAAGX,OAAO;IAAC;AAC5E;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASc;IACd,OAAO,CAACb,QAAgBc;QACtB,IAAI,OAAOA,gBAAgB,UAAU;YACnC;QACF;QAEA,MAAMC,qBACJd,QAAQe,cAAc,CAACpB,+BAA+BI,WAAW,EAAE;QAErE,IAAI,CAACe,mBAAmBE,QAAQ,CAACH,cAAc;YAC7CC,mBAAmBG,IAAI,CAACJ;QAC1B;QAEAb,QAAQC,cAAc,CACpBN,+BACAmB,oBACAf;IAEJ;AACF"}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/entity.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_OPTIONS_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n POLYMORPHIC_VARIANT_METADATA_KEY,\n} from './types.js';\nimport { EntityRegistry } from './entity-registry.js';\nimport { PolymorphicRegistry } from './polymorphic-registry.js';\n\n/**\n * Options for Entity decorator\n */\nexport interface EntityOptions {\n /**\n * Optional name for the entity. Used for discriminated entity deserialization.\n * If not specified, the class name will be used.\n * Must be unique across all entities - conflicts will throw an error.\n */\n name?: string;\n /**\n * Whether this entity represents a collection.\n * Collection entities must have a 'collection' property that is an array.\n * When serialized, collection entities are unwrapped to just their array.\n * When deserialized from an array, the array is wrapped in { collection: [...] }.\n */\n collection?: boolean;\n /**\n * Whether this entity represents a stringifiable value.\n * Stringifiable classes must have a 'value' property that is a string.\n * When serialized, stringifiable instances are unwrapped to just their string.\n * When deserialized from a string, the string is wrapped in { value: \"...\" }.\n */\n stringifiable?: boolean;\n /**\n * The name of the single \"wrapper\" property for entities that act as transparent wrappers.\n * When set, this property name is excluded from error paths during validation.\n * Used by @CollectionEntity ('collection') and @Stringifiable ('value').\n */\n wrapperProperty?: string;\n /**\n * Whether to register this entity in the EntityRegistry.\n * Set to false for dynamic entities to prevent memory leaks.\n * Defaults to true.\n */\n register?: boolean;\n}\n\n/**\n * Decorator that marks a class as an Entity.\n * This allows us to identify entity instances later.\n *\n * @param options - Optional configuration for the entity\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * name: string;\n * }\n *\n * @Entity({ name: 'CustomUser' })\n * class User {\n * name: string;\n * }\n *\n * @Entity({ collection: true })\n * class Tags {\n * @ArrayProperty(() => String)\n * collection: string[];\n * }\n * ```\n */\nexport function Entity(options: EntityOptions = {}): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return function (target: Function) {\n // Store metadata on the class constructor\n Reflect.defineMetadata(ENTITY_METADATA_KEY, true, target);\n\n // Determine the entity name - use provided name or fall back to class name\n const entityName = options.name ?? target.name;\n\n // Register the entity in the global registry (unless explicitly disabled)\n const shouldRegister = options.register !== false;\n if (shouldRegister) {\n EntityRegistry.register(entityName, target);\n }\n\n // Store the name in options for later retrieval\n const optionsWithName = { ...options, name: entityName };\n\n Reflect.defineMetadata(\n ENTITY_OPTIONS_METADATA_KEY,\n optionsWithName,\n target,\n );\n };\n}\n\n/**\n * Decorator that marks a class as a Collection Entity.\n * This is syntax sugar for @Entity({ collection: true }).\n *\n * Collection entities must have a 'collection' property that is an array.\n * When serialized with EntityUtils.toJSON(), they are unwrapped to just the array.\n * When deserialized from an array, the array is wrapped in { collection: [...] }.\n *\n * @example\n * ```typescript\n * @CollectionEntity()\n * class Tags {\n * @ArrayProperty(() => String)\n * readonly collection: string[];\n *\n * constructor(data: { collection: string[] }) {\n * this.collection = data.collection;\n * }\n * }\n *\n * @Entity()\n * class Article {\n * @EntityProperty(() => Tags)\n * tags!: Tags;\n * }\n *\n * const article = new Article(...);\n * const json = EntityUtils.toJSON(article);\n * // { tags: [\"tag1\", \"tag2\"] } - unwrapped to array\n *\n * // Also works when serializing the collection directly:\n * const tagsJson = EntityUtils.toJSON(tags);\n * // [\"tag1\", \"tag2\"] - unwrapped to array\n * ```\n */\nexport function CollectionEntity(\n options: Pick<EntityOptions, 'name'> = {},\n): ClassDecorator {\n return Entity({\n collection: true,\n wrapperProperty: 'collection',\n ...options,\n });\n}\n\n/**\n * Decorator that marks a class as Stringifiable.\n * This is syntax sugar for @Entity({ stringifiable: true }).\n *\n * Stringifiable classes must have a 'value' property that is a string.\n * When serialized with EntityUtils.toJSON(), they are unwrapped to just the string.\n * When deserialized from a string, the string is wrapped in { value: \"...\" }.\n *\n * @example\n * ```typescript\n * @Stringifiable()\n * class UserId {\n * @StringProperty()\n * readonly value: string;\n *\n * constructor(data: { value: string }) {\n * this.value = data.value;\n * }\n * }\n *\n * @Entity()\n * class User {\n * @EntityProperty(() => UserId)\n * id!: UserId;\n * }\n *\n * const user = new User(...);\n * const json = EntityUtils.toJSON(user);\n * // { id: \"user-123\" } - unwrapped to string\n *\n * // Also works when serializing the stringifiable directly:\n * const userId = new UserId({ value: \"user-123\" });\n * const idJson = EntityUtils.toJSON(userId);\n * // \"user-123\" - unwrapped to string\n *\n * // Parse from string:\n * const parsed = await EntityUtils.parse(UserId, \"user-456\");\n * // UserId { value: \"user-456\" }\n * ```\n */\nexport function Stringifiable(\n options: Pick<EntityOptions, 'name'> = {},\n): ClassDecorator {\n return Entity({ stringifiable: true, wrapperProperty: 'value', ...options });\n}\n\n/**\n * Decorator that marks a method as an entity validator.\n * The method should return an array of Problems.\n *\n * @example\n * ```typescript\n * @Entity()\n * class User {\n * @Property({ type: () => String }) firstName!: string;\n * @Property({ type: () => String }) lastName!: string;\n *\n * @EntityValidator()\n * validateNames(): Problem[] {\n * const problems: Problem[] = [];\n * if (this.firstName === this.lastName) {\n * problems.push(new Problem({\n * property: 'firstName',\n * message: 'First and last name cannot be the same'\n * }));\n * }\n * return problems;\n * }\n * }\n * ```\n */\nexport function EntityValidator(): MethodDecorator {\n return (target: object, propertyKey: string | symbol): void => {\n if (typeof propertyKey !== 'string') {\n return;\n }\n\n const existingValidators: string[] =\n Reflect.getOwnMetadata(ENTITY_VALIDATOR_METADATA_KEY, target) || [];\n\n if (!existingValidators.includes(propertyKey)) {\n existingValidators.push(propertyKey);\n }\n\n Reflect.defineMetadata(\n ENTITY_VALIDATOR_METADATA_KEY,\n existingValidators,\n target,\n );\n };\n}\n\n/**\n * Decorator that registers a class as a polymorphic variant of a base class.\n *\n * Used for class hierarchies where an abstract base class has multiple concrete implementations,\n * and a discriminator property determines which variant to instantiate during parsing.\n *\n * @param baseClass - The base class this variant extends (must have a @PolymorphicProperty)\n * @param discriminatorValue - The value of the discriminator property that identifies this variant\n *\n * @example\n * ```typescript\n * enum SchemaPropertyType {\n * STRING = 'string',\n * NUMBER = 'number',\n * }\n *\n * @Entity()\n * abstract class SchemaProperty {\n * @StringProperty({ minLength: 1 })\n * name!: string;\n *\n * @PolymorphicProperty(SchemaPropertyType)\n * type!: SchemaPropertyType;\n * }\n *\n * @Entity()\n * @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)\n * class StringSchemaProperty extends SchemaProperty {\n * readonly type = SchemaPropertyType.STRING;\n *\n * @IntProperty({ optional: true })\n * minLength?: number;\n *\n * constructor(data: { name: string; minLength?: number }) {\n * super({ ...data, type: SchemaPropertyType.STRING });\n * this.minLength = data.minLength;\n * }\n * }\n *\n * @Entity()\n * @PolymorphicVariant(SchemaProperty, SchemaPropertyType.NUMBER)\n * class NumberSchemaProperty extends SchemaProperty {\n * readonly type = SchemaPropertyType.NUMBER;\n *\n * @NumberProperty({ optional: true })\n * min?: number;\n *\n * constructor(data: { name: string; min?: number }) {\n * super({ ...data, type: SchemaPropertyType.NUMBER });\n * this.min = data.min;\n * }\n * }\n *\n * // Parsing automatically selects the correct variant based on 'type'\n * const data = { name: 'age', type: 'number', min: 0 };\n * const prop = await EntityUtils.parse(SchemaProperty, data);\n * // prop is NumberSchemaProperty instance\n * ```\n */\nexport function PolymorphicVariant<T extends Function>(\n baseClass: T,\n discriminatorValue: unknown,\n): ClassDecorator {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n return function (target: Function) {\n // Register the variant in the registry\n PolymorphicRegistry.registerVariant(baseClass, discriminatorValue, target);\n\n // Store metadata on the class for introspection\n Reflect.defineMetadata(\n POLYMORPHIC_VARIANT_METADATA_KEY,\n { baseClass, discriminatorValue },\n target,\n );\n };\n}\n"],"names":["ENTITY_METADATA_KEY","ENTITY_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","POLYMORPHIC_VARIANT_METADATA_KEY","EntityRegistry","PolymorphicRegistry","Entity","options","target","Reflect","defineMetadata","entityName","name","shouldRegister","register","optionsWithName","CollectionEntity","collection","wrapperProperty","Stringifiable","stringifiable","EntityValidator","propertyKey","existingValidators","getOwnMetadata","includes","push","PolymorphicVariant","baseClass","discriminatorValue","registerVariant"],"mappings":"AAAA,6DAA6D,GAC7D,SACEA,mBAAmB,EACnBC,2BAA2B,EAC3BC,6BAA6B,EAC7BC,gCAAgC,QAC3B,aAAa;AACpB,SAASC,cAAc,QAAQ,uBAAuB;AACtD,SAASC,mBAAmB,QAAQ,4BAA4B;AAwChE;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,OAAOC,UAAyB,CAAC,CAAC;IAChD,sEAAsE;IACtE,OAAO,SAAUC,MAAgB;QAC/B,0CAA0C;QAC1CC,QAAQC,cAAc,CAACV,qBAAqB,MAAMQ;QAElD,2EAA2E;QAC3E,MAAMG,aAAaJ,QAAQK,IAAI,IAAIJ,OAAOI,IAAI;QAE9C,0EAA0E;QAC1E,MAAMC,iBAAiBN,QAAQO,QAAQ,KAAK;QAC5C,IAAID,gBAAgB;YAClBT,eAAeU,QAAQ,CAACH,YAAYH;QACtC;QAEA,gDAAgD;QAChD,MAAMO,kBAAkB;YAAE,GAAGR,OAAO;YAAEK,MAAMD;QAAW;QAEvDF,QAAQC,cAAc,CACpBT,6BACAc,iBACAP;IAEJ;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCC,GACD,OAAO,SAASQ,iBACdT,UAAuC,CAAC,CAAC;IAEzC,OAAOD,OAAO;QACZW,YAAY;QACZC,iBAAiB;QACjB,GAAGX,OAAO;IACZ;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCC,GACD,OAAO,SAASY,cACdZ,UAAuC,CAAC,CAAC;IAEzC,OAAOD,OAAO;QAAEc,eAAe;QAAMF,iBAAiB;QAAS,GAAGX,OAAO;IAAC;AAC5E;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASc;IACd,OAAO,CAACb,QAAgBc;QACtB,IAAI,OAAOA,gBAAgB,UAAU;YACnC;QACF;QAEA,MAAMC,qBACJd,QAAQe,cAAc,CAACtB,+BAA+BM,WAAW,EAAE;QAErE,IAAI,CAACe,mBAAmBE,QAAQ,CAACH,cAAc;YAC7CC,mBAAmBG,IAAI,CAACJ;QAC1B;QAEAb,QAAQC,cAAc,CACpBR,+BACAqB,oBACAf;IAEJ;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DC,GACD,OAAO,SAASmB,mBACdC,SAAY,EACZC,kBAA2B;IAE3B,sEAAsE;IACtE,OAAO,SAAUrB,MAAgB;QAC/B,uCAAuC;QACvCH,oBAAoByB,eAAe,CAACF,WAAWC,oBAAoBrB;QAEnE,gDAAgD;QAChDC,QAAQC,cAAc,CACpBP,kCACA;YAAEyB;YAAWC;QAAmB,GAChCrB;IAEJ;AACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry for polymorphic entity variants.
|
|
3
|
+
* Maps base classes to their discriminator properties and variant implementations.
|
|
4
|
+
*/
|
|
5
|
+
export declare class PolymorphicRegistry {
|
|
6
|
+
/**
|
|
7
|
+
* Maps base class -> discriminator property name
|
|
8
|
+
*/
|
|
9
|
+
private static discriminatorProperties;
|
|
10
|
+
/**
|
|
11
|
+
* Maps base class -> (discriminator value -> variant class)
|
|
12
|
+
*/
|
|
13
|
+
private static variants;
|
|
14
|
+
/**
|
|
15
|
+
* Registers a discriminator property for a base class.
|
|
16
|
+
* @param baseClass - The base class that has a polymorphic discriminator
|
|
17
|
+
* @param propertyName - The name of the discriminator property
|
|
18
|
+
* @throws Error if a discriminator property is already registered for this class
|
|
19
|
+
*/
|
|
20
|
+
static setDiscriminatorProperty(baseClass: Function, propertyName: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Gets the discriminator property name for a base class.
|
|
23
|
+
* @param baseClass - The base class to look up
|
|
24
|
+
* @returns The discriminator property name, or undefined if not found
|
|
25
|
+
*/
|
|
26
|
+
static getDiscriminatorProperty(baseClass: Function): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Registers a variant class for a base class and discriminator value.
|
|
29
|
+
* @param baseClass - The base class this variant extends
|
|
30
|
+
* @param discriminatorValue - The value of the discriminator property that identifies this variant
|
|
31
|
+
* @param variantClass - The concrete variant class
|
|
32
|
+
* @throws Error if a variant is already registered for this discriminator value
|
|
33
|
+
*/
|
|
34
|
+
static registerVariant(baseClass: Function, discriminatorValue: unknown, variantClass: Function): void;
|
|
35
|
+
/**
|
|
36
|
+
* Gets the variant class for a base class and discriminator value.
|
|
37
|
+
* @param baseClass - The base class to look up
|
|
38
|
+
* @param discriminatorValue - The discriminator value to match
|
|
39
|
+
* @returns The variant class, or undefined if not found
|
|
40
|
+
*/
|
|
41
|
+
static getVariant(baseClass: Function, discriminatorValue: unknown): Function | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Gets all registered variants for a base class.
|
|
44
|
+
* @param baseClass - The base class to look up
|
|
45
|
+
* @returns Array of variant registrations with their discriminator values
|
|
46
|
+
*/
|
|
47
|
+
static getAllVariants(baseClass: Function): Array<{
|
|
48
|
+
discriminatorValue: unknown;
|
|
49
|
+
variantClass: Function;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Clears all registrations. Useful for testing.
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
static clear(): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=polymorphic-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polymorphic-registry.d.ts","sourceRoot":"","sources":["../../src/lib/polymorphic-registry.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA+B;IAErE;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+C;IAEtE;;;;;OAKG;IACH,MAAM,CAAC,wBAAwB,CAC7B,SAAS,EAAE,QAAQ,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI;IAYP;;;;OAIG;IACH,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS;IAIxE;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CACpB,SAAS,EAAE,QAAQ,EACnB,kBAAkB,EAAE,OAAO,EAC3B,YAAY,EAAE,QAAQ,GACrB,IAAI;IAoBP;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CACf,SAAS,EAAE,QAAQ,EACnB,kBAAkB,EAAE,OAAO,GAC1B,QAAQ,GAAG,SAAS;IAMvB;;;;OAIG;IACH,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,GAAG,KAAK,CAAC;QAChD,kBAAkB,EAAE,OAAO,CAAC;QAC5B,YAAY,EAAE,QAAQ,CAAC;KACxB,CAAC;IAYF;;;OAGG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;CAIrB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-function-type */ /**
|
|
2
|
+
* Registry for polymorphic entity variants.
|
|
3
|
+
* Maps base classes to their discriminator properties and variant implementations.
|
|
4
|
+
*/ export class PolymorphicRegistry {
|
|
5
|
+
static{
|
|
6
|
+
/**
|
|
7
|
+
* Maps base class -> discriminator property name
|
|
8
|
+
*/ this.discriminatorProperties = new Map();
|
|
9
|
+
}
|
|
10
|
+
static{
|
|
11
|
+
/**
|
|
12
|
+
* Maps base class -> (discriminator value -> variant class)
|
|
13
|
+
*/ this.variants = new Map();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Registers a discriminator property for a base class.
|
|
17
|
+
* @param baseClass - The base class that has a polymorphic discriminator
|
|
18
|
+
* @param propertyName - The name of the discriminator property
|
|
19
|
+
* @throws Error if a discriminator property is already registered for this class
|
|
20
|
+
*/ static setDiscriminatorProperty(baseClass, propertyName) {
|
|
21
|
+
const existing = this.discriminatorProperties.get(baseClass);
|
|
22
|
+
if (existing && existing !== propertyName) {
|
|
23
|
+
throw new Error(`Base class '${baseClass.name}' already has a polymorphic discriminator property '${existing}'. ` + `Cannot register another discriminator '${propertyName}'. ` + `Only one discriminator property per class hierarchy is allowed.`);
|
|
24
|
+
}
|
|
25
|
+
this.discriminatorProperties.set(baseClass, propertyName);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Gets the discriminator property name for a base class.
|
|
29
|
+
* @param baseClass - The base class to look up
|
|
30
|
+
* @returns The discriminator property name, or undefined if not found
|
|
31
|
+
*/ static getDiscriminatorProperty(baseClass) {
|
|
32
|
+
return this.discriminatorProperties.get(baseClass);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Registers a variant class for a base class and discriminator value.
|
|
36
|
+
* @param baseClass - The base class this variant extends
|
|
37
|
+
* @param discriminatorValue - The value of the discriminator property that identifies this variant
|
|
38
|
+
* @param variantClass - The concrete variant class
|
|
39
|
+
* @throws Error if a variant is already registered for this discriminator value
|
|
40
|
+
*/ static registerVariant(baseClass, discriminatorValue, variantClass) {
|
|
41
|
+
let variantMap = this.variants.get(baseClass);
|
|
42
|
+
if (!variantMap) {
|
|
43
|
+
variantMap = new Map();
|
|
44
|
+
this.variants.set(baseClass, variantMap);
|
|
45
|
+
}
|
|
46
|
+
const existing = variantMap.get(discriminatorValue);
|
|
47
|
+
if (existing && existing !== variantClass) {
|
|
48
|
+
throw new Error(`Duplicate polymorphic variant registration for base class '${baseClass.name}' ` + `with discriminator value '${String(discriminatorValue)}'. ` + `Existing variant: '${existing.name}', attempted: '${variantClass.name}'. ` + `Each discriminator value must map to exactly one variant class.`);
|
|
49
|
+
}
|
|
50
|
+
variantMap.set(discriminatorValue, variantClass);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Gets the variant class for a base class and discriminator value.
|
|
54
|
+
* @param baseClass - The base class to look up
|
|
55
|
+
* @param discriminatorValue - The discriminator value to match
|
|
56
|
+
* @returns The variant class, or undefined if not found
|
|
57
|
+
*/ static getVariant(baseClass, discriminatorValue) {
|
|
58
|
+
const variantMap = this.variants.get(baseClass);
|
|
59
|
+
if (!variantMap) return undefined;
|
|
60
|
+
return variantMap.get(discriminatorValue);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gets all registered variants for a base class.
|
|
64
|
+
* @param baseClass - The base class to look up
|
|
65
|
+
* @returns Array of variant registrations with their discriminator values
|
|
66
|
+
*/ static getAllVariants(baseClass) {
|
|
67
|
+
const variantMap = this.variants.get(baseClass);
|
|
68
|
+
if (!variantMap) return [];
|
|
69
|
+
return Array.from(variantMap.entries()).map(([discriminatorValue, variantClass])=>({
|
|
70
|
+
discriminatorValue,
|
|
71
|
+
variantClass
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Clears all registrations. Useful for testing.
|
|
76
|
+
* @internal
|
|
77
|
+
*/ static clear() {
|
|
78
|
+
this.discriminatorProperties.clear();
|
|
79
|
+
this.variants.clear();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=polymorphic-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/polymorphic-registry.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\n/**\n * Registry for polymorphic entity variants.\n * Maps base classes to their discriminator properties and variant implementations.\n */\nexport class PolymorphicRegistry {\n /**\n * Maps base class -> discriminator property name\n */\n private static discriminatorProperties = new Map<Function, string>();\n\n /**\n * Maps base class -> (discriminator value -> variant class)\n */\n private static variants = new Map<Function, Map<unknown, Function>>();\n\n /**\n * Registers a discriminator property for a base class.\n * @param baseClass - The base class that has a polymorphic discriminator\n * @param propertyName - The name of the discriminator property\n * @throws Error if a discriminator property is already registered for this class\n */\n static setDiscriminatorProperty(\n baseClass: Function,\n propertyName: string,\n ): void {\n const existing = this.discriminatorProperties.get(baseClass);\n if (existing && existing !== propertyName) {\n throw new Error(\n `Base class '${baseClass.name}' already has a polymorphic discriminator property '${existing}'. ` +\n `Cannot register another discriminator '${propertyName}'. ` +\n `Only one discriminator property per class hierarchy is allowed.`,\n );\n }\n this.discriminatorProperties.set(baseClass, propertyName);\n }\n\n /**\n * Gets the discriminator property name for a base class.\n * @param baseClass - The base class to look up\n * @returns The discriminator property name, or undefined if not found\n */\n static getDiscriminatorProperty(baseClass: Function): string | undefined {\n return this.discriminatorProperties.get(baseClass);\n }\n\n /**\n * Registers a variant class for a base class and discriminator value.\n * @param baseClass - The base class this variant extends\n * @param discriminatorValue - The value of the discriminator property that identifies this variant\n * @param variantClass - The concrete variant class\n * @throws Error if a variant is already registered for this discriminator value\n */\n static registerVariant(\n baseClass: Function,\n discriminatorValue: unknown,\n variantClass: Function,\n ): void {\n let variantMap = this.variants.get(baseClass);\n if (!variantMap) {\n variantMap = new Map();\n this.variants.set(baseClass, variantMap);\n }\n\n const existing = variantMap.get(discriminatorValue);\n if (existing && existing !== variantClass) {\n throw new Error(\n `Duplicate polymorphic variant registration for base class '${baseClass.name}' ` +\n `with discriminator value '${String(discriminatorValue)}'. ` +\n `Existing variant: '${existing.name}', attempted: '${variantClass.name}'. ` +\n `Each discriminator value must map to exactly one variant class.`,\n );\n }\n\n variantMap.set(discriminatorValue, variantClass);\n }\n\n /**\n * Gets the variant class for a base class and discriminator value.\n * @param baseClass - The base class to look up\n * @param discriminatorValue - The discriminator value to match\n * @returns The variant class, or undefined if not found\n */\n static getVariant(\n baseClass: Function,\n discriminatorValue: unknown,\n ): Function | undefined {\n const variantMap = this.variants.get(baseClass);\n if (!variantMap) return undefined;\n return variantMap.get(discriminatorValue);\n }\n\n /**\n * Gets all registered variants for a base class.\n * @param baseClass - The base class to look up\n * @returns Array of variant registrations with their discriminator values\n */\n static getAllVariants(baseClass: Function): Array<{\n discriminatorValue: unknown;\n variantClass: Function;\n }> {\n const variantMap = this.variants.get(baseClass);\n if (!variantMap) return [];\n\n return Array.from(variantMap.entries()).map(\n ([discriminatorValue, variantClass]) => ({\n discriminatorValue,\n variantClass,\n }),\n );\n }\n\n /**\n * Clears all registrations. Useful for testing.\n * @internal\n */\n static clear(): void {\n this.discriminatorProperties.clear();\n this.variants.clear();\n }\n}\n"],"names":["PolymorphicRegistry","discriminatorProperties","Map","variants","setDiscriminatorProperty","baseClass","propertyName","existing","get","Error","name","set","getDiscriminatorProperty","registerVariant","discriminatorValue","variantClass","variantMap","String","getVariant","undefined","getAllVariants","Array","from","entries","map","clear"],"mappings":"AAAA,6DAA6D,GAE7D;;;CAGC,GACD,OAAO,MAAMA;;QACX;;GAEC,QACcC,0BAA0B,IAAIC;;;QAE7C;;GAEC,QACcC,WAAW,IAAID;;IAE9B;;;;;GAKC,GACD,OAAOE,yBACLC,SAAmB,EACnBC,YAAoB,EACd;QACN,MAAMC,WAAW,IAAI,CAACN,uBAAuB,CAACO,GAAG,CAACH;QAClD,IAAIE,YAAYA,aAAaD,cAAc;YACzC,MAAM,IAAIG,MACR,CAAC,YAAY,EAAEJ,UAAUK,IAAI,CAAC,oDAAoD,EAAEH,SAAS,GAAG,CAAC,GAC/F,CAAC,uCAAuC,EAAED,aAAa,GAAG,CAAC,GAC3D,CAAC,+DAA+D,CAAC;QAEvE;QACA,IAAI,CAACL,uBAAuB,CAACU,GAAG,CAACN,WAAWC;IAC9C;IAEA;;;;GAIC,GACD,OAAOM,yBAAyBP,SAAmB,EAAsB;QACvE,OAAO,IAAI,CAACJ,uBAAuB,CAACO,GAAG,CAACH;IAC1C;IAEA;;;;;;GAMC,GACD,OAAOQ,gBACLR,SAAmB,EACnBS,kBAA2B,EAC3BC,YAAsB,EAChB;QACN,IAAIC,aAAa,IAAI,CAACb,QAAQ,CAACK,GAAG,CAACH;QACnC,IAAI,CAACW,YAAY;YACfA,aAAa,IAAId;YACjB,IAAI,CAACC,QAAQ,CAACQ,GAAG,CAACN,WAAWW;QAC/B;QAEA,MAAMT,WAAWS,WAAWR,GAAG,CAACM;QAChC,IAAIP,YAAYA,aAAaQ,cAAc;YACzC,MAAM,IAAIN,MACR,CAAC,2DAA2D,EAAEJ,UAAUK,IAAI,CAAC,EAAE,CAAC,GAC9E,CAAC,0BAA0B,EAAEO,OAAOH,oBAAoB,GAAG,CAAC,GAC5D,CAAC,mBAAmB,EAAEP,SAASG,IAAI,CAAC,eAAe,EAAEK,aAAaL,IAAI,CAAC,GAAG,CAAC,GAC3E,CAAC,+DAA+D,CAAC;QAEvE;QAEAM,WAAWL,GAAG,CAACG,oBAAoBC;IACrC;IAEA;;;;;GAKC,GACD,OAAOG,WACLb,SAAmB,EACnBS,kBAA2B,EACL;QACtB,MAAME,aAAa,IAAI,CAACb,QAAQ,CAACK,GAAG,CAACH;QACrC,IAAI,CAACW,YAAY,OAAOG;QACxB,OAAOH,WAAWR,GAAG,CAACM;IACxB;IAEA;;;;GAIC,GACD,OAAOM,eAAef,SAAmB,EAGtC;QACD,MAAMW,aAAa,IAAI,CAACb,QAAQ,CAACK,GAAG,CAACH;QACrC,IAAI,CAACW,YAAY,OAAO,EAAE;QAE1B,OAAOK,MAAMC,IAAI,CAACN,WAAWO,OAAO,IAAIC,GAAG,CACzC,CAAC,CAACV,oBAAoBC,aAAa,GAAM,CAAA;gBACvCD;gBACAC;YACF,CAAA;IAEJ;IAEA;;;GAGC,GACD,OAAOU,QAAc;QACnB,IAAI,CAACxB,uBAAuB,CAACwB,KAAK;QAClC,IAAI,CAACtB,QAAQ,CAACsB,KAAK;IACrB;AACF"}
|
package/dist/lib/property.d.ts
CHANGED
|
@@ -345,4 +345,49 @@ export declare function discriminatedEntityPropertyOptions(options?: Omit<Proper
|
|
|
345
345
|
export declare function DiscriminatedEntityProperty(options?: Omit<PropertyOptions<any, any>, 'type' | 'discriminated'> & {
|
|
346
346
|
discriminatorProperty?: string;
|
|
347
347
|
}): PropertyDecorator;
|
|
348
|
+
/**
|
|
349
|
+
* Decorator that marks a property as a polymorphic discriminator.
|
|
350
|
+
*
|
|
351
|
+
* Used for class hierarchies where an abstract base class has multiple concrete implementations,
|
|
352
|
+
* and the discriminator property value determines which subclass to instantiate.
|
|
353
|
+
*
|
|
354
|
+
* The discriminator is a regular class property (not injected during serialization like @DiscriminatedEntityProperty).
|
|
355
|
+
*
|
|
356
|
+
* This decorator can be used standalone (it will treat the property as a string) or combined
|
|
357
|
+
* with another type decorator for more specific typing.
|
|
358
|
+
*
|
|
359
|
+
* @param enumType - Optional enum or union type for the discriminator (used for validation and schema generation)
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* enum SchemaPropertyType {
|
|
364
|
+
* STRING = 'string',
|
|
365
|
+
* NUMBER = 'number',
|
|
366
|
+
* }
|
|
367
|
+
*
|
|
368
|
+
* @Entity()
|
|
369
|
+
* abstract class SchemaProperty {
|
|
370
|
+
* @StringProperty({ minLength: 1 })
|
|
371
|
+
* name!: string;
|
|
372
|
+
*
|
|
373
|
+
* @PolymorphicProperty(SchemaPropertyType)
|
|
374
|
+
* type!: SchemaPropertyType;
|
|
375
|
+
* }
|
|
376
|
+
*
|
|
377
|
+
* @Entity()
|
|
378
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
|
|
379
|
+
* class StringSchemaProperty extends SchemaProperty {
|
|
380
|
+
* type = SchemaPropertyType.STRING;
|
|
381
|
+
*
|
|
382
|
+
* @IntProperty({ optional: true })
|
|
383
|
+
* minLength?: number;
|
|
384
|
+
* }
|
|
385
|
+
*
|
|
386
|
+
* // Parsing automatically instantiates the correct subclass
|
|
387
|
+
* const data = { name: 'age', type: 'string', minLength: 5 };
|
|
388
|
+
* const prop = await EntityUtils.parse(SchemaProperty, data);
|
|
389
|
+
* // prop is StringSchemaProperty instance
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
export declare function PolymorphicProperty(enumType?: any): PropertyDecorator;
|
|
348
393
|
//# sourceMappingURL=property.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property.d.ts","sourceRoot":"","sources":["../../src/lib/property.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"property.d.ts","sourceRoot":"","sources":["../../src/lib/property.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/property.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-wrapper-object-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { isEqual } from 'lodash-es';
|
|
2
|
-
import { PROPERTY_METADATA_KEY, PROPERTY_OPTIONS_METADATA_KEY } from './types.js';
|
|
2
|
+
import { PROPERTY_METADATA_KEY, PROPERTY_OPTIONS_METADATA_KEY, POLYMORPHIC_PROPERTY_METADATA_KEY } from './types.js';
|
|
3
3
|
import { enumValidator, intValidator, minLengthValidator, maxLengthValidator, patternValidator, minValidator, maxValidator, arrayMinLengthValidator, arrayMaxLengthValidator } from './validators.js';
|
|
4
|
+
import { PolymorphicRegistry } from './polymorphic-registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* Property decorator that marks class properties with metadata.
|
|
6
7
|
* This decorator can be used to identify and track properties within classes.
|
|
@@ -488,5 +489,79 @@ export const SerializableProperty = (type, data = {})=>Property({
|
|
|
488
489
|
export function DiscriminatedEntityProperty(options) {
|
|
489
490
|
return Property(discriminatedEntityPropertyOptions(options));
|
|
490
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Decorator that marks a property as a polymorphic discriminator.
|
|
494
|
+
*
|
|
495
|
+
* Used for class hierarchies where an abstract base class has multiple concrete implementations,
|
|
496
|
+
* and the discriminator property value determines which subclass to instantiate.
|
|
497
|
+
*
|
|
498
|
+
* The discriminator is a regular class property (not injected during serialization like @DiscriminatedEntityProperty).
|
|
499
|
+
*
|
|
500
|
+
* This decorator can be used standalone (it will treat the property as a string) or combined
|
|
501
|
+
* with another type decorator for more specific typing.
|
|
502
|
+
*
|
|
503
|
+
* @param enumType - Optional enum or union type for the discriminator (used for validation and schema generation)
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```typescript
|
|
507
|
+
* enum SchemaPropertyType {
|
|
508
|
+
* STRING = 'string',
|
|
509
|
+
* NUMBER = 'number',
|
|
510
|
+
* }
|
|
511
|
+
*
|
|
512
|
+
* @Entity()
|
|
513
|
+
* abstract class SchemaProperty {
|
|
514
|
+
* @StringProperty({ minLength: 1 })
|
|
515
|
+
* name!: string;
|
|
516
|
+
*
|
|
517
|
+
* @PolymorphicProperty(SchemaPropertyType)
|
|
518
|
+
* type!: SchemaPropertyType;
|
|
519
|
+
* }
|
|
520
|
+
*
|
|
521
|
+
* @Entity()
|
|
522
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
|
|
523
|
+
* class StringSchemaProperty extends SchemaProperty {
|
|
524
|
+
* type = SchemaPropertyType.STRING;
|
|
525
|
+
*
|
|
526
|
+
* @IntProperty({ optional: true })
|
|
527
|
+
* minLength?: number;
|
|
528
|
+
* }
|
|
529
|
+
*
|
|
530
|
+
* // Parsing automatically instantiates the correct subclass
|
|
531
|
+
* const data = { name: 'age', type: 'string', minLength: 5 };
|
|
532
|
+
* const prop = await EntityUtils.parse(SchemaProperty, data);
|
|
533
|
+
* // prop is StringSchemaProperty instance
|
|
534
|
+
* ```
|
|
535
|
+
*/ export function PolymorphicProperty(enumType) {
|
|
536
|
+
return (target, propertyKey)=>{
|
|
537
|
+
if (typeof propertyKey !== 'string') {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
// Store the polymorphic property metadata
|
|
541
|
+
Reflect.defineMetadata(POLYMORPHIC_PROPERTY_METADATA_KEY, propertyKey, target.constructor);
|
|
542
|
+
// Register in PolymorphicRegistry
|
|
543
|
+
PolymorphicRegistry.setDiscriminatorProperty(target.constructor, propertyKey);
|
|
544
|
+
// Check if property already has options (from another decorator)
|
|
545
|
+
const existingOptions = Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, target, propertyKey);
|
|
546
|
+
if (existingOptions) {
|
|
547
|
+
// Update existing options to add polymorphic flags
|
|
548
|
+
const updatedOptions = {
|
|
549
|
+
...existingOptions,
|
|
550
|
+
polymorphicDiscriminator: true,
|
|
551
|
+
polymorphicEnumType: enumType
|
|
552
|
+
};
|
|
553
|
+
Reflect.defineMetadata(PROPERTY_OPTIONS_METADATA_KEY, updatedOptions, target, propertyKey);
|
|
554
|
+
} else {
|
|
555
|
+
// No existing decorator - apply Property decorator with string type
|
|
556
|
+
// (enum discriminators are typically strings)
|
|
557
|
+
const options = {
|
|
558
|
+
type: ()=>String,
|
|
559
|
+
polymorphicDiscriminator: true,
|
|
560
|
+
polymorphicEnumType: enumType
|
|
561
|
+
};
|
|
562
|
+
Property(options)(target, propertyKey);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
491
566
|
|
|
492
567
|
//# sourceMappingURL=property.js.map
|
package/dist/lib/property.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/property.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-wrapper-object-types */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { isEqual } from 'lodash-es';\nimport {\n AnyCtor,\n type CtorLike,\n type InstanceOfCtorLike,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n} from './types.js';\nimport {\n enumValidator,\n intValidator,\n minLengthValidator,\n maxLengthValidator,\n patternValidator,\n minValidator,\n maxValidator,\n arrayMinLengthValidator,\n arrayMaxLengthValidator,\n} from './validators.js';\n\n/**\n * Property decorator that marks class properties with metadata.\n * This decorator can be used to identify and track properties within classes.\n *\n * @param options - Configuration for the property (type is required)\n *\n * @example\n * class User {\n * @Property({ type: () => String })\n * name: string;\n *\n * @Property({ type: () => String, equals: (a, b) => a.toLowerCase() === b.toLowerCase() })\n * email: string;\n *\n * @Property({ type: () => Number })\n * age: number;\n * }\n */\nexport function Property<T, C extends CtorLike<T>>(\n options: PropertyOptions<T, C>,\n): PropertyDecorator {\n return (target: object, propertyKey: string | symbol): void => {\n if (typeof propertyKey !== 'string') {\n return;\n }\n\n const existingProperties: string[] =\n Reflect.getOwnMetadata(PROPERTY_METADATA_KEY, target) || [];\n\n if (!existingProperties.includes(propertyKey)) {\n existingProperties.push(propertyKey);\n }\n\n Reflect.defineMetadata(PROPERTY_METADATA_KEY, existingProperties, target);\n\n if (options.passthrough === true) {\n if (options.array === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and array: true. Passthrough cannot be combined with array.`,\n );\n }\n if (options.optional === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and optional: true. Passthrough cannot be combined with optional.`,\n );\n }\n if (options.sparse === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and sparse: true. Passthrough cannot be combined with sparse.`,\n );\n }\n if (\n options.serialize !== undefined ||\n options.deserialize !== undefined\n ) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and custom serialize/deserialize functions. Passthrough cannot be combined with serialize or deserialize.`,\n );\n }\n }\n\n if (options.sparse === true && options.array !== true) {\n throw new Error(\n `Property '${propertyKey}' has sparse: true but array is not true. The sparse option only applies to arrays.`,\n );\n }\n\n if (options.arrayValidators && options.array !== true) {\n throw new Error(\n `Property '${propertyKey}' has arrayValidators defined but array is not true. The arrayValidators option only applies to arrays.`,\n );\n }\n\n // Validate serialize/deserialize pairing\n const hasSerialize = options.serialize !== undefined;\n const hasDeserialize = options.deserialize !== undefined;\n if (hasSerialize !== hasDeserialize) {\n throw new Error(\n `Property '${propertyKey}' must define both serialize and deserialize functions, or neither. Found only ${hasSerialize ? 'serialize' : 'deserialize'}.`,\n );\n }\n\n const existingOptions: Record<\n string,\n PropertyOptions<any, any>\n > = Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, target) || {};\n\n existingOptions[propertyKey] = options;\n\n Reflect.defineMetadata(\n PROPERTY_OPTIONS_METADATA_KEY,\n existingOptions,\n target,\n );\n };\n}\n\n/**\n * Helper decorator for string properties\n * @example\n * class User {\n * @StringProperty()\n * name!: string;\n *\n * @StringProperty({ optional: true })\n * nickname?: string;\n *\n * @StringProperty({ minLength: 3, maxLength: 50 })\n * username!: string;\n *\n * @StringProperty({ pattern: /^[a-z]+$/ })\n * slug!: string;\n * }\n */\n/**\n * Creates property options for a string property with optional validation\n * Used internally by StringProperty decorator and Props.String helper\n */\nexport function stringPropertyOptions(\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'> & {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n patternMessage?: string;\n },\n): PropertyOptions<string, StringConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.minLength !== undefined) {\n validators.unshift(minLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n validators.unshift(maxLengthValidator(options.maxLength));\n }\n if (options?.pattern !== undefined) {\n validators.unshift(\n patternValidator(options.pattern, options.patternMessage),\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, pattern, patternMessage, ...restOptions } =\n options || {};\n\n return {\n ...restOptions,\n type: () => String,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for string properties\n * @example\n * class User {\n * @StringProperty()\n * name!: string;\n *\n * @StringProperty({ optional: true })\n * nickname?: string;\n *\n * @StringProperty({ minLength: 2, maxLength: 50 })\n * username!: string;\n *\n * @StringProperty({ pattern: /^[a-z]+$/, patternMessage: 'Must be lowercase letters only' })\n * slug!: string;\n * }\n */\nexport function StringProperty(\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'> & {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n patternMessage?: string;\n },\n): PropertyDecorator {\n return Property(stringPropertyOptions(options));\n}\n\n/**\n * Creates property options for an enum property\n * Used internally by EnumProperty decorator and Props.Enum helper\n */\nexport function enumPropertyOptions<T extends Record<string, string>>(\n enumType: T,\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'>,\n): PropertyOptions<string, StringConstructor> {\n const validators = options?.validators\n ? [enumValidator(enumType), ...options.validators]\n : [enumValidator(enumType)];\n\n return { ...options, type: () => String, validators };\n}\n\n/**\n * Helper decorator for enum properties (string enums)\n * Validates that the string value matches one of the enum values\n * @param enumType - The enum object (e.g., MyEnum)\n * @param options - Additional property options\n * @example\n * enum Status {\n * Active = 'active',\n * Inactive = 'inactive'\n * }\n *\n * class User {\n * @EnumProperty(Status)\n * status!: Status;\n *\n * @EnumProperty(Status, { optional: true })\n * previousStatus?: Status;\n * }\n */\nexport function EnumProperty<T extends Record<string, string>>(\n enumType: T,\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(enumPropertyOptions(enumType, options));\n}\n\n/**\n * Creates property options for a number property\n * Used internally by NumberProperty decorator and Props.Number helper\n */\nexport function numberPropertyOptions(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyOptions<number, NumberConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.min !== undefined) {\n validators.unshift(minValidator(options.min));\n }\n if (options?.max !== undefined) {\n validators.unshift(maxValidator(options.max));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { min, max, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type: () => Number,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for number properties\n * @example\n * class User {\n * @NumberProperty()\n * age!: number;\n *\n * @NumberProperty({ optional: true })\n * score?: number;\n *\n * @NumberProperty({ min: 0, max: 100 })\n * percentage!: number;\n * }\n */\nexport function NumberProperty(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyDecorator {\n return Property(numberPropertyOptions(options));\n}\n\n/**\n * Creates property options for an integer property\n * Used internally by IntProperty decorator and Props.Int helper\n */\nexport function intPropertyOptions(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyOptions<number, NumberConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.min !== undefined) {\n validators.unshift(minValidator(options.min));\n }\n if (options?.max !== undefined) {\n validators.unshift(maxValidator(options.max));\n }\n\n validators.unshift(intValidator());\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { min, max, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type: () => Number,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for integer properties\n * Validates that the number is an integer (no decimal places)\n * @example\n * class User {\n * @IntProperty()\n * age!: number;\n *\n * @IntProperty({ optional: true })\n * count?: number;\n *\n * @IntProperty({ min: 0, max: 100 })\n * percentage!: number;\n * }\n */\nexport function IntProperty(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyDecorator {\n return Property(intPropertyOptions(options));\n}\n\n/**\n * Creates property options for a boolean property\n * Used internally by BooleanProperty decorator and Props.Boolean helper\n */\nexport function booleanPropertyOptions(\n options?: Omit<PropertyOptions<boolean, BooleanConstructor>, 'type'>,\n): PropertyOptions<boolean, BooleanConstructor> {\n return { ...options, type: () => Boolean };\n}\n\n/**\n * Helper decorator for boolean properties\n * @example\n * class User {\n * @BooleanProperty()\n * active!: boolean;\n *\n * @BooleanProperty({ optional: true })\n * verified?: boolean;\n * }\n */\nexport function BooleanProperty(\n options?: Omit<PropertyOptions<boolean, BooleanConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(booleanPropertyOptions(options));\n}\n\n/**\n * Creates property options for a Date property\n * Used internally by DateProperty decorator and Props.Date helper\n */\nexport function datePropertyOptions(\n options?: Omit<PropertyOptions<Date, DateConstructor>, 'type'>,\n): PropertyOptions<Date, DateConstructor> {\n return { ...options, type: () => Date };\n}\n\n/**\n * Helper decorator for Date properties\n * @example\n * class User {\n * @DateProperty()\n * createdAt!: Date;\n *\n * @DateProperty({ optional: true })\n * deletedAt?: Date;\n * }\n */\nexport function DateProperty(\n options?: Omit<PropertyOptions<Date, DateConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(datePropertyOptions(options));\n}\n\n/**\n * Creates property options for a BigInt property\n * Used internally by BigIntProperty decorator and Props.BigInt helper\n */\nexport function bigIntPropertyOptions(\n options?: Omit<PropertyOptions<bigint, BigIntConstructor>, 'type'>,\n): PropertyOptions<bigint, BigIntConstructor> {\n return { ...options, type: () => BigInt };\n}\n\n/**\n * Helper decorator for BigInt properties\n * @example\n * class User {\n * @BigIntProperty()\n * id!: bigint;\n *\n * @BigIntProperty({ optional: true })\n * balance?: bigint;\n * }\n */\nexport function BigIntProperty(\n options?: Omit<PropertyOptions<bigint, BigIntConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(bigIntPropertyOptions(options));\n}\n\n/**\n * Creates property options for an entity property\n * Used internally by EntityProperty decorator and Props.Entity helper\n */\nexport function entityPropertyOptions<\n T,\n C extends AnyCtor<T> & { new (data: any): T },\n>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type'>,\n): PropertyOptions<T, C> {\n return { ...options, type };\n}\n\n/**\n * Helper decorator for entity properties\n * @example\n * class User {\n * @EntityProperty(() => Address)\n * address!: Address;\n *\n * @EntityProperty(() => Profile, { optional: true })\n * profile?: Profile;\n * }\n */\nexport function EntityProperty<\n T,\n C extends AnyCtor<T> & { new (data: any): T },\n>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type'>,\n): PropertyDecorator {\n return Property<T, C>(entityPropertyOptions(type, options));\n}\n\n/**\n * Creates property options for an array property\n * Used internally by ArrayProperty decorator and Props.Array helper\n */\nexport function arrayPropertyOptions<T, C extends CtorLike<T>>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type' | 'array'> & {\n minLength?: number;\n maxLength?: number;\n },\n): PropertyOptions<T, C> {\n const validators = [...(options?.arrayValidators || [])];\n\n if (options?.minLength !== undefined) {\n validators.unshift(arrayMinLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n validators.unshift(arrayMaxLengthValidator(options.maxLength));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type,\n array: true,\n arrayValidators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for array properties\n * @example\n * class User {\n * @ArrayProperty(() => String)\n * tags!: string[];\n *\n * @ArrayProperty(() => Phone)\n * phones!: Phone[];\n *\n * @ArrayProperty(() => Number, { optional: true })\n * scores?: number[];\n *\n * @ArrayProperty(() => String, { sparse: true })\n * sparseList!: (string | null)[];\n *\n * @ArrayProperty(() => String, { minLength: 1, maxLength: 10 })\n * limitedList!: string[];\n * }\n */\nexport function ArrayProperty<T, C extends CtorLike<T>>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type' | 'array'> & {\n minLength?: number;\n maxLength?: number;\n },\n): PropertyDecorator {\n const arrayValidators = [...(options?.arrayValidators || [])];\n\n if (options?.minLength !== undefined) {\n arrayValidators.unshift(arrayMinLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n arrayValidators.unshift(arrayMaxLengthValidator(options.maxLength));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, ...restOptions } = options || {};\n\n return Property({\n ...restOptions,\n type,\n array: true,\n arrayValidators: arrayValidators.length > 0 ? arrayValidators : undefined,\n });\n}\n\n/**\n * Creates property options for a passthrough property\n * Used internally by PassthroughProperty decorator and Props.Passthrough helper\n */\nexport function passthroughPropertyOptions(\n options?: Omit<PropertyOptions, 'type' | 'passthrough'>,\n): PropertyOptions {\n return { ...options, type: () => Object, passthrough: true };\n}\n\n/**\n * Helper decorator for passthrough properties that bypass type validation.\n * Use this for generic types like Record<string, unknown>, any, or custom objects.\n * @example\n * class Config {\n * @PassthroughProperty()\n * metadata!: Record<string, unknown>;\n *\n * @PassthroughProperty()\n * customData!: any;\n * }\n */\nexport function PassthroughProperty(): PropertyDecorator {\n return Property(passthroughPropertyOptions());\n}\n\n/**\n * Property options for stringifiable types (types with toString() and static parse())\n * Used internally by StringifiableProperty decorator and EntityProps.Stringifiable helper\n */\nexport function stringifiablePropertyOptions<\n T extends { equals?(other: T): boolean; toString(): string },\n C extends CtorLike<T> & { parse(value: string): T },\n>(\n type: () => C,\n options?: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n >,\n): PropertyOptions<T, C> {\n return {\n ...options,\n type,\n equals: (a, b) => (a.equals ? a.equals(b) : a.toString() === b.toString()),\n serialize: (value) => value.toString(),\n deserialize: (value) => {\n if (typeof value === 'string') {\n return type().parse(value) as InstanceOfCtorLike<C>;\n }\n throw new Error(`Invalid value ${type().name}: ${String(value)}`);\n },\n };\n}\n\nexport const StringifiableProperty = <\n T extends { equals?(other: T): boolean; toString(): string },\n C extends CtorLike<T> & { parse(value: string): T },\n>(\n type: () => C,\n data: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n > = {},\n): PropertyDecorator =>\n Property<T, C>(stringifiablePropertyOptions(type, data));\n\nexport const SerializableProperty = <\n T extends { equals?(other: T): boolean; toJSON(): unknown },\n C extends CtorLike<T> & { parse(value: unknown): T },\n>(\n type: () => C,\n data: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n > = {},\n) =>\n Property({\n ...data,\n type,\n equals: (a: T, b: T) =>\n a.equals ? a.equals(b) : isEqual(a.toJSON(), b.toJSON()),\n serialize: (value: T) => value.toJSON(),\n deserialize: (value: unknown) => {\n return type().parse(value) as InstanceOfCtorLike<C>;\n },\n });\n\n/**\n * Helper decorator for discriminated entity properties.\n * The entity type is determined at runtime using a discriminator property.\n * Unlike EntityProperty, this does not require the type parameter upfront.\n *\n * @param options - Configuration for the discriminated property\n *\n * @example\n * ```typescript\n * // Define entity types\n * @Entity({ name: 'Circle' })\n * class Circle {\n * @StringProperty() readonly type = 'Circle';\n * @NumberProperty() radius!: number;\n * constructor(data: Partial<Circle>) { Object.assign(this, data); }\n * }\n *\n * @Entity({ name: 'Rectangle' })\n * class Rectangle {\n * @StringProperty() readonly type = 'Rectangle';\n * @NumberProperty() width!: number;\n * @NumberProperty() height!: number;\n * constructor(data: Partial<Rectangle>) { Object.assign(this, data); }\n * }\n *\n * // Use discriminated property\n * @Entity()\n * class Drawing {\n * @DiscriminatedEntityProperty()\n * shape!: Circle | Rectangle;\n *\n * @DiscriminatedEntityProperty({ discriminatorProperty: 'entityType' })\n * item!: BaseItem;\n * }\n *\n * // When serialized, the discriminator is included inline:\n * // { shape: { __type: 'Circle', radius: 5 } }\n *\n * // When deserialized, the discriminator is used to determine the type:\n * const drawing = await EntityUtils.parse(Drawing, {\n * shape: { __type: 'Circle', radius: 5 }\n * });\n * // drawing.shape is a Circle instance\n * ```\n */\n/**\n * Creates property options for a discriminated entity property\n * Used internally by DiscriminatedEntityProperty decorator and EntityProps.DiscriminatedEntity helper\n */\nexport function discriminatedEntityPropertyOptions(\n options?: Omit<PropertyOptions<any, any>, 'type' | 'discriminated'> & {\n discriminatorProperty?: string;\n },\n): PropertyOptions<any, any> {\n const discriminatorProperty = options?.discriminatorProperty ?? '__type';\n\n return {\n ...options,\n discriminated: true,\n discriminatorProperty,\n };\n}\n\nexport function DiscriminatedEntityProperty(\n options?: Omit<PropertyOptions<any, any>, 'type' | 'discriminated'> & {\n discriminatorProperty?: string;\n },\n): PropertyDecorator {\n return Property(discriminatedEntityPropertyOptions(options));\n}\n"],"names":["isEqual","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","enumValidator","intValidator","minLengthValidator","maxLengthValidator","patternValidator","minValidator","maxValidator","arrayMinLengthValidator","arrayMaxLengthValidator","Property","options","target","propertyKey","existingProperties","Reflect","getOwnMetadata","includes","push","defineMetadata","passthrough","array","Error","optional","sparse","serialize","undefined","deserialize","arrayValidators","hasSerialize","hasDeserialize","existingOptions","stringPropertyOptions","validators","minLength","unshift","maxLength","pattern","patternMessage","restOptions","type","String","length","StringProperty","enumPropertyOptions","enumType","EnumProperty","numberPropertyOptions","min","max","Number","NumberProperty","intPropertyOptions","IntProperty","booleanPropertyOptions","Boolean","BooleanProperty","datePropertyOptions","Date","DateProperty","bigIntPropertyOptions","BigInt","BigIntProperty","entityPropertyOptions","EntityProperty","arrayPropertyOptions","ArrayProperty","passthroughPropertyOptions","Object","PassthroughProperty","stringifiablePropertyOptions","equals","a","b","toString","value","parse","name","StringifiableProperty","data","SerializableProperty","toJSON","discriminatedEntityPropertyOptions","discriminatorProperty","discriminated","DiscriminatedEntityProperty"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/property.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-wrapper-object-types */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { isEqual } from 'lodash-es';\nimport {\n AnyCtor,\n type CtorLike,\n type InstanceOfCtorLike,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n POLYMORPHIC_PROPERTY_METADATA_KEY,\n PropertyOptions,\n} from './types.js';\nimport {\n enumValidator,\n intValidator,\n minLengthValidator,\n maxLengthValidator,\n patternValidator,\n minValidator,\n maxValidator,\n arrayMinLengthValidator,\n arrayMaxLengthValidator,\n} from './validators.js';\nimport { PolymorphicRegistry } from './polymorphic-registry.js';\n\n/**\n * Property decorator that marks class properties with metadata.\n * This decorator can be used to identify and track properties within classes.\n *\n * @param options - Configuration for the property (type is required)\n *\n * @example\n * class User {\n * @Property({ type: () => String })\n * name: string;\n *\n * @Property({ type: () => String, equals: (a, b) => a.toLowerCase() === b.toLowerCase() })\n * email: string;\n *\n * @Property({ type: () => Number })\n * age: number;\n * }\n */\nexport function Property<T, C extends CtorLike<T>>(\n options: PropertyOptions<T, C>,\n): PropertyDecorator {\n return (target: object, propertyKey: string | symbol): void => {\n if (typeof propertyKey !== 'string') {\n return;\n }\n\n const existingProperties: string[] =\n Reflect.getOwnMetadata(PROPERTY_METADATA_KEY, target) || [];\n\n if (!existingProperties.includes(propertyKey)) {\n existingProperties.push(propertyKey);\n }\n\n Reflect.defineMetadata(PROPERTY_METADATA_KEY, existingProperties, target);\n\n if (options.passthrough === true) {\n if (options.array === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and array: true. Passthrough cannot be combined with array.`,\n );\n }\n if (options.optional === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and optional: true. Passthrough cannot be combined with optional.`,\n );\n }\n if (options.sparse === true) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and sparse: true. Passthrough cannot be combined with sparse.`,\n );\n }\n if (\n options.serialize !== undefined ||\n options.deserialize !== undefined\n ) {\n throw new Error(\n `Property '${propertyKey}' has passthrough: true and custom serialize/deserialize functions. Passthrough cannot be combined with serialize or deserialize.`,\n );\n }\n }\n\n if (options.sparse === true && options.array !== true) {\n throw new Error(\n `Property '${propertyKey}' has sparse: true but array is not true. The sparse option only applies to arrays.`,\n );\n }\n\n if (options.arrayValidators && options.array !== true) {\n throw new Error(\n `Property '${propertyKey}' has arrayValidators defined but array is not true. The arrayValidators option only applies to arrays.`,\n );\n }\n\n // Validate serialize/deserialize pairing\n const hasSerialize = options.serialize !== undefined;\n const hasDeserialize = options.deserialize !== undefined;\n if (hasSerialize !== hasDeserialize) {\n throw new Error(\n `Property '${propertyKey}' must define both serialize and deserialize functions, or neither. Found only ${hasSerialize ? 'serialize' : 'deserialize'}.`,\n );\n }\n\n const existingOptions: Record<\n string,\n PropertyOptions<any, any>\n > = Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, target) || {};\n\n existingOptions[propertyKey] = options;\n\n Reflect.defineMetadata(\n PROPERTY_OPTIONS_METADATA_KEY,\n existingOptions,\n target,\n );\n };\n}\n\n/**\n * Helper decorator for string properties\n * @example\n * class User {\n * @StringProperty()\n * name!: string;\n *\n * @StringProperty({ optional: true })\n * nickname?: string;\n *\n * @StringProperty({ minLength: 3, maxLength: 50 })\n * username!: string;\n *\n * @StringProperty({ pattern: /^[a-z]+$/ })\n * slug!: string;\n * }\n */\n/**\n * Creates property options for a string property with optional validation\n * Used internally by StringProperty decorator and Props.String helper\n */\nexport function stringPropertyOptions(\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'> & {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n patternMessage?: string;\n },\n): PropertyOptions<string, StringConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.minLength !== undefined) {\n validators.unshift(minLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n validators.unshift(maxLengthValidator(options.maxLength));\n }\n if (options?.pattern !== undefined) {\n validators.unshift(\n patternValidator(options.pattern, options.patternMessage),\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, pattern, patternMessage, ...restOptions } =\n options || {};\n\n return {\n ...restOptions,\n type: () => String,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for string properties\n * @example\n * class User {\n * @StringProperty()\n * name!: string;\n *\n * @StringProperty({ optional: true })\n * nickname?: string;\n *\n * @StringProperty({ minLength: 2, maxLength: 50 })\n * username!: string;\n *\n * @StringProperty({ pattern: /^[a-z]+$/, patternMessage: 'Must be lowercase letters only' })\n * slug!: string;\n * }\n */\nexport function StringProperty(\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'> & {\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n patternMessage?: string;\n },\n): PropertyDecorator {\n return Property(stringPropertyOptions(options));\n}\n\n/**\n * Creates property options for an enum property\n * Used internally by EnumProperty decorator and Props.Enum helper\n */\nexport function enumPropertyOptions<T extends Record<string, string>>(\n enumType: T,\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'>,\n): PropertyOptions<string, StringConstructor> {\n const validators = options?.validators\n ? [enumValidator(enumType), ...options.validators]\n : [enumValidator(enumType)];\n\n return { ...options, type: () => String, validators };\n}\n\n/**\n * Helper decorator for enum properties (string enums)\n * Validates that the string value matches one of the enum values\n * @param enumType - The enum object (e.g., MyEnum)\n * @param options - Additional property options\n * @example\n * enum Status {\n * Active = 'active',\n * Inactive = 'inactive'\n * }\n *\n * class User {\n * @EnumProperty(Status)\n * status!: Status;\n *\n * @EnumProperty(Status, { optional: true })\n * previousStatus?: Status;\n * }\n */\nexport function EnumProperty<T extends Record<string, string>>(\n enumType: T,\n options?: Omit<PropertyOptions<string, StringConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(enumPropertyOptions(enumType, options));\n}\n\n/**\n * Creates property options for a number property\n * Used internally by NumberProperty decorator and Props.Number helper\n */\nexport function numberPropertyOptions(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyOptions<number, NumberConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.min !== undefined) {\n validators.unshift(minValidator(options.min));\n }\n if (options?.max !== undefined) {\n validators.unshift(maxValidator(options.max));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { min, max, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type: () => Number,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for number properties\n * @example\n * class User {\n * @NumberProperty()\n * age!: number;\n *\n * @NumberProperty({ optional: true })\n * score?: number;\n *\n * @NumberProperty({ min: 0, max: 100 })\n * percentage!: number;\n * }\n */\nexport function NumberProperty(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyDecorator {\n return Property(numberPropertyOptions(options));\n}\n\n/**\n * Creates property options for an integer property\n * Used internally by IntProperty decorator and Props.Int helper\n */\nexport function intPropertyOptions(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyOptions<number, NumberConstructor> {\n const validators = [...(options?.validators || [])];\n\n if (options?.min !== undefined) {\n validators.unshift(minValidator(options.min));\n }\n if (options?.max !== undefined) {\n validators.unshift(maxValidator(options.max));\n }\n\n validators.unshift(intValidator());\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { min, max, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type: () => Number,\n validators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for integer properties\n * Validates that the number is an integer (no decimal places)\n * @example\n * class User {\n * @IntProperty()\n * age!: number;\n *\n * @IntProperty({ optional: true })\n * count?: number;\n *\n * @IntProperty({ min: 0, max: 100 })\n * percentage!: number;\n * }\n */\nexport function IntProperty(\n options?: Omit<PropertyOptions<number, NumberConstructor>, 'type'> & {\n min?: number;\n max?: number;\n },\n): PropertyDecorator {\n return Property(intPropertyOptions(options));\n}\n\n/**\n * Creates property options for a boolean property\n * Used internally by BooleanProperty decorator and Props.Boolean helper\n */\nexport function booleanPropertyOptions(\n options?: Omit<PropertyOptions<boolean, BooleanConstructor>, 'type'>,\n): PropertyOptions<boolean, BooleanConstructor> {\n return { ...options, type: () => Boolean };\n}\n\n/**\n * Helper decorator for boolean properties\n * @example\n * class User {\n * @BooleanProperty()\n * active!: boolean;\n *\n * @BooleanProperty({ optional: true })\n * verified?: boolean;\n * }\n */\nexport function BooleanProperty(\n options?: Omit<PropertyOptions<boolean, BooleanConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(booleanPropertyOptions(options));\n}\n\n/**\n * Creates property options for a Date property\n * Used internally by DateProperty decorator and Props.Date helper\n */\nexport function datePropertyOptions(\n options?: Omit<PropertyOptions<Date, DateConstructor>, 'type'>,\n): PropertyOptions<Date, DateConstructor> {\n return { ...options, type: () => Date };\n}\n\n/**\n * Helper decorator for Date properties\n * @example\n * class User {\n * @DateProperty()\n * createdAt!: Date;\n *\n * @DateProperty({ optional: true })\n * deletedAt?: Date;\n * }\n */\nexport function DateProperty(\n options?: Omit<PropertyOptions<Date, DateConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(datePropertyOptions(options));\n}\n\n/**\n * Creates property options for a BigInt property\n * Used internally by BigIntProperty decorator and Props.BigInt helper\n */\nexport function bigIntPropertyOptions(\n options?: Omit<PropertyOptions<bigint, BigIntConstructor>, 'type'>,\n): PropertyOptions<bigint, BigIntConstructor> {\n return { ...options, type: () => BigInt };\n}\n\n/**\n * Helper decorator for BigInt properties\n * @example\n * class User {\n * @BigIntProperty()\n * id!: bigint;\n *\n * @BigIntProperty({ optional: true })\n * balance?: bigint;\n * }\n */\nexport function BigIntProperty(\n options?: Omit<PropertyOptions<bigint, BigIntConstructor>, 'type'>,\n): PropertyDecorator {\n return Property(bigIntPropertyOptions(options));\n}\n\n/**\n * Creates property options for an entity property\n * Used internally by EntityProperty decorator and Props.Entity helper\n */\nexport function entityPropertyOptions<\n T,\n C extends AnyCtor<T> & { new (data: any): T },\n>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type'>,\n): PropertyOptions<T, C> {\n return { ...options, type };\n}\n\n/**\n * Helper decorator for entity properties\n * @example\n * class User {\n * @EntityProperty(() => Address)\n * address!: Address;\n *\n * @EntityProperty(() => Profile, { optional: true })\n * profile?: Profile;\n * }\n */\nexport function EntityProperty<\n T,\n C extends AnyCtor<T> & { new (data: any): T },\n>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type'>,\n): PropertyDecorator {\n return Property<T, C>(entityPropertyOptions(type, options));\n}\n\n/**\n * Creates property options for an array property\n * Used internally by ArrayProperty decorator and Props.Array helper\n */\nexport function arrayPropertyOptions<T, C extends CtorLike<T>>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type' | 'array'> & {\n minLength?: number;\n maxLength?: number;\n },\n): PropertyOptions<T, C> {\n const validators = [...(options?.arrayValidators || [])];\n\n if (options?.minLength !== undefined) {\n validators.unshift(arrayMinLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n validators.unshift(arrayMaxLengthValidator(options.maxLength));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, ...restOptions } = options || {};\n\n return {\n ...restOptions,\n type,\n array: true,\n arrayValidators: validators.length > 0 ? validators : undefined,\n };\n}\n\n/**\n * Helper decorator for array properties\n * @example\n * class User {\n * @ArrayProperty(() => String)\n * tags!: string[];\n *\n * @ArrayProperty(() => Phone)\n * phones!: Phone[];\n *\n * @ArrayProperty(() => Number, { optional: true })\n * scores?: number[];\n *\n * @ArrayProperty(() => String, { sparse: true })\n * sparseList!: (string | null)[];\n *\n * @ArrayProperty(() => String, { minLength: 1, maxLength: 10 })\n * limitedList!: string[];\n * }\n */\nexport function ArrayProperty<T, C extends CtorLike<T>>(\n type: () => C,\n options?: Omit<PropertyOptions<T, C>, 'type' | 'array'> & {\n minLength?: number;\n maxLength?: number;\n },\n): PropertyDecorator {\n const arrayValidators = [...(options?.arrayValidators || [])];\n\n if (options?.minLength !== undefined) {\n arrayValidators.unshift(arrayMinLengthValidator(options.minLength));\n }\n if (options?.maxLength !== undefined) {\n arrayValidators.unshift(arrayMaxLengthValidator(options.maxLength));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { minLength, maxLength, ...restOptions } = options || {};\n\n return Property({\n ...restOptions,\n type,\n array: true,\n arrayValidators: arrayValidators.length > 0 ? arrayValidators : undefined,\n });\n}\n\n/**\n * Creates property options for a passthrough property\n * Used internally by PassthroughProperty decorator and Props.Passthrough helper\n */\nexport function passthroughPropertyOptions(\n options?: Omit<PropertyOptions, 'type' | 'passthrough'>,\n): PropertyOptions {\n return { ...options, type: () => Object, passthrough: true };\n}\n\n/**\n * Helper decorator for passthrough properties that bypass type validation.\n * Use this for generic types like Record<string, unknown>, any, or custom objects.\n * @example\n * class Config {\n * @PassthroughProperty()\n * metadata!: Record<string, unknown>;\n *\n * @PassthroughProperty()\n * customData!: any;\n * }\n */\nexport function PassthroughProperty(): PropertyDecorator {\n return Property(passthroughPropertyOptions());\n}\n\n/**\n * Property options for stringifiable types (types with toString() and static parse())\n * Used internally by StringifiableProperty decorator and EntityProps.Stringifiable helper\n */\nexport function stringifiablePropertyOptions<\n T extends { equals?(other: T): boolean; toString(): string },\n C extends CtorLike<T> & { parse(value: string): T },\n>(\n type: () => C,\n options?: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n >,\n): PropertyOptions<T, C> {\n return {\n ...options,\n type,\n equals: (a, b) => (a.equals ? a.equals(b) : a.toString() === b.toString()),\n serialize: (value) => value.toString(),\n deserialize: (value) => {\n if (typeof value === 'string') {\n return type().parse(value) as InstanceOfCtorLike<C>;\n }\n throw new Error(`Invalid value ${type().name}: ${String(value)}`);\n },\n };\n}\n\nexport const StringifiableProperty = <\n T extends { equals?(other: T): boolean; toString(): string },\n C extends CtorLike<T> & { parse(value: string): T },\n>(\n type: () => C,\n data: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n > = {},\n): PropertyDecorator =>\n Property<T, C>(stringifiablePropertyOptions(type, data));\n\nexport const SerializableProperty = <\n T extends { equals?(other: T): boolean; toJSON(): unknown },\n C extends CtorLike<T> & { parse(value: unknown): T },\n>(\n type: () => C,\n data: Omit<\n PropertyOptions<T, C>,\n 'serialize' | 'deserialize' | 'passthrough' | 'type' | 'equals'\n > = {},\n) =>\n Property({\n ...data,\n type,\n equals: (a: T, b: T) =>\n a.equals ? a.equals(b) : isEqual(a.toJSON(), b.toJSON()),\n serialize: (value: T) => value.toJSON(),\n deserialize: (value: unknown) => {\n return type().parse(value) as InstanceOfCtorLike<C>;\n },\n });\n\n/**\n * Helper decorator for discriminated entity properties.\n * The entity type is determined at runtime using a discriminator property.\n * Unlike EntityProperty, this does not require the type parameter upfront.\n *\n * @param options - Configuration for the discriminated property\n *\n * @example\n * ```typescript\n * // Define entity types\n * @Entity({ name: 'Circle' })\n * class Circle {\n * @StringProperty() readonly type = 'Circle';\n * @NumberProperty() radius!: number;\n * constructor(data: Partial<Circle>) { Object.assign(this, data); }\n * }\n *\n * @Entity({ name: 'Rectangle' })\n * class Rectangle {\n * @StringProperty() readonly type = 'Rectangle';\n * @NumberProperty() width!: number;\n * @NumberProperty() height!: number;\n * constructor(data: Partial<Rectangle>) { Object.assign(this, data); }\n * }\n *\n * // Use discriminated property\n * @Entity()\n * class Drawing {\n * @DiscriminatedEntityProperty()\n * shape!: Circle | Rectangle;\n *\n * @DiscriminatedEntityProperty({ discriminatorProperty: 'entityType' })\n * item!: BaseItem;\n * }\n *\n * // When serialized, the discriminator is included inline:\n * // { shape: { __type: 'Circle', radius: 5 } }\n *\n * // When deserialized, the discriminator is used to determine the type:\n * const drawing = await EntityUtils.parse(Drawing, {\n * shape: { __type: 'Circle', radius: 5 }\n * });\n * // drawing.shape is a Circle instance\n * ```\n */\n/**\n * Creates property options for a discriminated entity property\n * Used internally by DiscriminatedEntityProperty decorator and EntityProps.DiscriminatedEntity helper\n */\nexport function discriminatedEntityPropertyOptions(\n options?: Omit<PropertyOptions<any, any>, 'type' | 'discriminated'> & {\n discriminatorProperty?: string;\n },\n): PropertyOptions<any, any> {\n const discriminatorProperty = options?.discriminatorProperty ?? '__type';\n\n return {\n ...options,\n discriminated: true,\n discriminatorProperty,\n };\n}\n\nexport function DiscriminatedEntityProperty(\n options?: Omit<PropertyOptions<any, any>, 'type' | 'discriminated'> & {\n discriminatorProperty?: string;\n },\n): PropertyDecorator {\n return Property(discriminatedEntityPropertyOptions(options));\n}\n\n/**\n * Decorator that marks a property as a polymorphic discriminator.\n *\n * Used for class hierarchies where an abstract base class has multiple concrete implementations,\n * and the discriminator property value determines which subclass to instantiate.\n *\n * The discriminator is a regular class property (not injected during serialization like @DiscriminatedEntityProperty).\n *\n * This decorator can be used standalone (it will treat the property as a string) or combined\n * with another type decorator for more specific typing.\n *\n * @param enumType - Optional enum or union type for the discriminator (used for validation and schema generation)\n *\n * @example\n * ```typescript\n * enum SchemaPropertyType {\n * STRING = 'string',\n * NUMBER = 'number',\n * }\n *\n * @Entity()\n * abstract class SchemaProperty {\n * @StringProperty({ minLength: 1 })\n * name!: string;\n *\n * @PolymorphicProperty(SchemaPropertyType)\n * type!: SchemaPropertyType;\n * }\n *\n * @Entity()\n * @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)\n * class StringSchemaProperty extends SchemaProperty {\n * type = SchemaPropertyType.STRING;\n *\n * @IntProperty({ optional: true })\n * minLength?: number;\n * }\n *\n * // Parsing automatically instantiates the correct subclass\n * const data = { name: 'age', type: 'string', minLength: 5 };\n * const prop = await EntityUtils.parse(SchemaProperty, data);\n * // prop is StringSchemaProperty instance\n * ```\n */\nexport function PolymorphicProperty(enumType?: any): PropertyDecorator {\n return (target: object, propertyKey: string | symbol): void => {\n if (typeof propertyKey !== 'string') {\n return;\n }\n\n // Store the polymorphic property metadata\n Reflect.defineMetadata(\n POLYMORPHIC_PROPERTY_METADATA_KEY,\n propertyKey,\n target.constructor,\n );\n\n // Register in PolymorphicRegistry\n PolymorphicRegistry.setDiscriminatorProperty(\n target.constructor,\n propertyKey,\n );\n\n // Check if property already has options (from another decorator)\n const existingOptions: PropertyOptions | undefined = Reflect.getOwnMetadata(\n PROPERTY_OPTIONS_METADATA_KEY,\n target,\n propertyKey,\n );\n\n if (existingOptions) {\n // Update existing options to add polymorphic flags\n const updatedOptions: PropertyOptions = {\n ...existingOptions,\n polymorphicDiscriminator: true,\n polymorphicEnumType: enumType,\n };\n\n Reflect.defineMetadata(\n PROPERTY_OPTIONS_METADATA_KEY,\n updatedOptions,\n target,\n propertyKey,\n );\n } else {\n // No existing decorator - apply Property decorator with string type\n // (enum discriminators are typically strings)\n const options: PropertyOptions = {\n type: () => String,\n polymorphicDiscriminator: true,\n polymorphicEnumType: enumType,\n };\n\n Property(options)(target, propertyKey);\n }\n };\n}\n"],"names":["isEqual","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","POLYMORPHIC_PROPERTY_METADATA_KEY","enumValidator","intValidator","minLengthValidator","maxLengthValidator","patternValidator","minValidator","maxValidator","arrayMinLengthValidator","arrayMaxLengthValidator","PolymorphicRegistry","Property","options","target","propertyKey","existingProperties","Reflect","getOwnMetadata","includes","push","defineMetadata","passthrough","array","Error","optional","sparse","serialize","undefined","deserialize","arrayValidators","hasSerialize","hasDeserialize","existingOptions","stringPropertyOptions","validators","minLength","unshift","maxLength","pattern","patternMessage","restOptions","type","String","length","StringProperty","enumPropertyOptions","enumType","EnumProperty","numberPropertyOptions","min","max","Number","NumberProperty","intPropertyOptions","IntProperty","booleanPropertyOptions","Boolean","BooleanProperty","datePropertyOptions","Date","DateProperty","bigIntPropertyOptions","BigInt","BigIntProperty","entityPropertyOptions","EntityProperty","arrayPropertyOptions","ArrayProperty","passthroughPropertyOptions","Object","PassthroughProperty","stringifiablePropertyOptions","equals","a","b","toString","value","parse","name","StringifiableProperty","data","SerializableProperty","toJSON","discriminatedEntityPropertyOptions","discriminatorProperty","discriminated","DiscriminatedEntityProperty","PolymorphicProperty","setDiscriminatorProperty","updatedOptions","polymorphicDiscriminator","polymorphicEnumType"],"mappings":"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"}
|