@rtpaulino/entity 0.24.2 → 0.26.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 +71 -0
- package/dist/lib/property.d.ts.map +1 -1
- package/dist/lib/property.js +109 -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 +2 -2
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,75 @@ 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, union type, or stringifiable type for the discriminator (used for validation and schema generation)
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* // With regular enum
|
|
364
|
+
* enum SchemaPropertyType {
|
|
365
|
+
* STRING = 'string',
|
|
366
|
+
* NUMBER = 'number',
|
|
367
|
+
* }
|
|
368
|
+
*
|
|
369
|
+
* @Entity()
|
|
370
|
+
* abstract class SchemaProperty {
|
|
371
|
+
* @StringProperty({ minLength: 1 })
|
|
372
|
+
* name!: string;
|
|
373
|
+
*
|
|
374
|
+
* @PolymorphicProperty(SchemaPropertyType)
|
|
375
|
+
* type!: SchemaPropertyType;
|
|
376
|
+
* }
|
|
377
|
+
*
|
|
378
|
+
* @Entity()
|
|
379
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
|
|
380
|
+
* class StringSchemaProperty extends SchemaProperty {
|
|
381
|
+
* type = SchemaPropertyType.STRING;
|
|
382
|
+
*
|
|
383
|
+
* @IntProperty({ optional: true })
|
|
384
|
+
* minLength?: number;
|
|
385
|
+
* }
|
|
386
|
+
*
|
|
387
|
+
* // With stringifiable type
|
|
388
|
+
* class Status {
|
|
389
|
+
* static ACTIVE = new Status('active');
|
|
390
|
+
* static INACTIVE = new Status('inactive');
|
|
391
|
+
*
|
|
392
|
+
* constructor(private value: string) {}
|
|
393
|
+
* toString() { return this.value; }
|
|
394
|
+
* static parse(value: string) {
|
|
395
|
+
* if (value === 'active') return Status.ACTIVE;
|
|
396
|
+
* if (value === 'inactive') return Status.INACTIVE;
|
|
397
|
+
* throw new Error('Invalid status');
|
|
398
|
+
* }
|
|
399
|
+
* }
|
|
400
|
+
*
|
|
401
|
+
* @Entity()
|
|
402
|
+
* abstract class Record {
|
|
403
|
+
* @PolymorphicProperty(() => Status)
|
|
404
|
+
* status!: Status;
|
|
405
|
+
* }
|
|
406
|
+
*
|
|
407
|
+
* // Parsing automatically instantiates the correct subclass
|
|
408
|
+
* const data = { name: 'age', type: 'string', minLength: 5 };
|
|
409
|
+
* const prop = await EntityUtils.parse(SchemaProperty, data);
|
|
410
|
+
* // prop is StringSchemaProperty instance
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
export declare function PolymorphicProperty<T extends {
|
|
414
|
+
equals?(other: T): boolean;
|
|
415
|
+
toString(): string;
|
|
416
|
+
}, C extends CtorLike<T> & {
|
|
417
|
+
parse(value: string): T;
|
|
418
|
+
}>(enumTypeOrFactory?: Record<string, string> | (() => C)): PropertyDecorator;
|
|
348
419
|
//# 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,112 @@ 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, union type, or stringifiable type for the discriminator (used for validation and schema generation)
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```typescript
|
|
507
|
+
* // With regular enum
|
|
508
|
+
* enum SchemaPropertyType {
|
|
509
|
+
* STRING = 'string',
|
|
510
|
+
* NUMBER = 'number',
|
|
511
|
+
* }
|
|
512
|
+
*
|
|
513
|
+
* @Entity()
|
|
514
|
+
* abstract class SchemaProperty {
|
|
515
|
+
* @StringProperty({ minLength: 1 })
|
|
516
|
+
* name!: string;
|
|
517
|
+
*
|
|
518
|
+
* @PolymorphicProperty(SchemaPropertyType)
|
|
519
|
+
* type!: SchemaPropertyType;
|
|
520
|
+
* }
|
|
521
|
+
*
|
|
522
|
+
* @Entity()
|
|
523
|
+
* @PolymorphicVariant(SchemaProperty, SchemaPropertyType.STRING)
|
|
524
|
+
* class StringSchemaProperty extends SchemaProperty {
|
|
525
|
+
* type = SchemaPropertyType.STRING;
|
|
526
|
+
*
|
|
527
|
+
* @IntProperty({ optional: true })
|
|
528
|
+
* minLength?: number;
|
|
529
|
+
* }
|
|
530
|
+
*
|
|
531
|
+
* // With stringifiable type
|
|
532
|
+
* class Status {
|
|
533
|
+
* static ACTIVE = new Status('active');
|
|
534
|
+
* static INACTIVE = new Status('inactive');
|
|
535
|
+
*
|
|
536
|
+
* constructor(private value: string) {}
|
|
537
|
+
* toString() { return this.value; }
|
|
538
|
+
* static parse(value: string) {
|
|
539
|
+
* if (value === 'active') return Status.ACTIVE;
|
|
540
|
+
* if (value === 'inactive') return Status.INACTIVE;
|
|
541
|
+
* throw new Error('Invalid status');
|
|
542
|
+
* }
|
|
543
|
+
* }
|
|
544
|
+
*
|
|
545
|
+
* @Entity()
|
|
546
|
+
* abstract class Record {
|
|
547
|
+
* @PolymorphicProperty(() => Status)
|
|
548
|
+
* status!: Status;
|
|
549
|
+
* }
|
|
550
|
+
*
|
|
551
|
+
* // Parsing automatically instantiates the correct subclass
|
|
552
|
+
* const data = { name: 'age', type: 'string', minLength: 5 };
|
|
553
|
+
* const prop = await EntityUtils.parse(SchemaProperty, data);
|
|
554
|
+
* // prop is StringSchemaProperty instance
|
|
555
|
+
* ```
|
|
556
|
+
*/ export function PolymorphicProperty(enumTypeOrFactory) {
|
|
557
|
+
return (target, propertyKey)=>{
|
|
558
|
+
if (typeof propertyKey !== 'string') {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
// Store the polymorphic property metadata
|
|
562
|
+
Reflect.defineMetadata(POLYMORPHIC_PROPERTY_METADATA_KEY, propertyKey, target.constructor);
|
|
563
|
+
// Register in PolymorphicRegistry
|
|
564
|
+
PolymorphicRegistry.setDiscriminatorProperty(target.constructor, propertyKey);
|
|
565
|
+
// Check if property already has options (from another decorator)
|
|
566
|
+
const existingOptions = Reflect.getOwnMetadata(PROPERTY_OPTIONS_METADATA_KEY, target, propertyKey);
|
|
567
|
+
if (existingOptions) {
|
|
568
|
+
// Update existing options to add polymorphic flags
|
|
569
|
+
const updatedOptions = {
|
|
570
|
+
...existingOptions,
|
|
571
|
+
polymorphicDiscriminator: true,
|
|
572
|
+
polymorphicEnumType: enumTypeOrFactory
|
|
573
|
+
};
|
|
574
|
+
Reflect.defineMetadata(PROPERTY_OPTIONS_METADATA_KEY, updatedOptions, target, propertyKey);
|
|
575
|
+
} else {
|
|
576
|
+
// No existing decorator - check if it's a stringifiable type or enum
|
|
577
|
+
const isStringifiable = typeof enumTypeOrFactory === 'function';
|
|
578
|
+
if (isStringifiable) {
|
|
579
|
+
// Apply StringifiableProperty decorator with polymorphic flags
|
|
580
|
+
const stringifiableOpts = stringifiablePropertyOptions(enumTypeOrFactory);
|
|
581
|
+
const options = {
|
|
582
|
+
...stringifiableOpts,
|
|
583
|
+
polymorphicDiscriminator: true,
|
|
584
|
+
polymorphicEnumType: enumTypeOrFactory
|
|
585
|
+
};
|
|
586
|
+
Property(options)(target, propertyKey);
|
|
587
|
+
} else {
|
|
588
|
+
// Apply Property decorator with string type (for enum discriminators)
|
|
589
|
+
const options = {
|
|
590
|
+
type: ()=>String,
|
|
591
|
+
polymorphicDiscriminator: true,
|
|
592
|
+
polymorphicEnumType: enumTypeOrFactory
|
|
593
|
+
};
|
|
594
|
+
Property(options)(target, propertyKey);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
}
|
|
491
599
|
|
|
492
600
|
//# sourceMappingURL=property.js.map
|