@rtpaulino/entity 0.22.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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-registry.d.ts +32 -0
- package/dist/lib/entity-registry.d.ts.map +1 -0
- package/dist/lib/entity-registry.js +42 -0
- package/dist/lib/entity-registry.js.map +1 -0
- package/dist/lib/entity-utils.d.ts +37 -0
- package/dist/lib/entity-utils.d.ts.map +1 -1
- package/dist/lib/entity-utils.js +124 -29
- package/dist/lib/entity-utils.js.map +1 -1
- package/dist/lib/entity.d.ts +19 -2
- package/dist/lib/entity.d.ts.map +1 -1
- package/dist/lib/entity.js +24 -7
- package/dist/lib/entity.js.map +1 -1
- package/dist/lib/property.d.ts +48 -0
- package/dist/lib/property.d.ts.map +1 -1
- package/dist/lib/property.js +52 -2
- package/dist/lib/property.js.map +1 -1
- package/dist/lib/test-entities.d.ts +474 -0
- package/dist/lib/test-entities.d.ts.map +1 -0
- package/dist/lib/test-entities.js +987 -0
- package/dist/lib/test-entities.js.map +1 -0
- package/dist/lib/types.d.ts +21 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/validation-utils.d.ts +6 -6
- package/dist/lib/validation-utils.d.ts.map +1 -1
- package/dist/lib/validation-utils.js +7 -7
- package/dist/lib/validation-utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/test-entities.ts"],"sourcesContent":["import 'reflect-metadata';\nimport { z } from 'zod';\nimport {\n Entity,\n CollectionEntity,\n Stringifiable,\n EntityValidator,\n} from './entity.js';\nimport {\n Property,\n StringProperty,\n NumberProperty,\n IntProperty,\n BooleanProperty,\n DateProperty,\n BigIntProperty,\n EnumProperty,\n EntityProperty,\n ArrayProperty,\n PassthroughProperty,\n SerializableProperty,\n StringifiableProperty,\n} from './property.js';\nimport { InjectedProperty } from './injected-property.js';\nimport { ZodProperty } from './zod-property.js';\nimport { Problem } from './problem.js';\n\n// ============================================================================\n// SIMPLE ENTITIES WITH PRIMITIVES\n// ============================================================================\n\n/**\n * Basic entity with common primitive types\n * Features: String, Number, Boolean properties\n */\n@Entity()\nexport class TestUser {\n @StringProperty() name!: string;\n @NumberProperty() age!: number;\n @BooleanProperty() active!: boolean;\n\n constructor(data: { name: string; age: number; active: boolean }) {\n this.name = data.name;\n this.age = data.age;\n this.active = data.active;\n }\n}\n\n/**\n * Entity with different primitive combinations\n * Features: String, Number, Int, Date properties\n */\n@Entity()\nexport class TestProduct {\n @StringProperty() id!: string;\n @StringProperty() name!: string;\n @NumberProperty() price!: number;\n @IntProperty() quantity!: number;\n @DateProperty() createdAt!: Date;\n\n constructor(data: {\n id: string;\n name: string;\n price: number;\n quantity: number;\n createdAt: Date;\n }) {\n this.id = data.id;\n this.name = data.name;\n this.price = data.price;\n this.quantity = data.quantity;\n this.createdAt = data.createdAt;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH SPECIAL TYPES\n// ============================================================================\n\n/**\n * Entity with Date and BigInt types\n * Features: DateProperty, BigIntProperty\n */\n@Entity()\nexport class EntityWithSpecialTypes {\n @DateProperty() timestamp!: Date;\n @BigIntProperty() largeNumber!: bigint;\n @StringProperty() label!: string;\n\n constructor(data: { timestamp: Date; largeNumber: bigint; label: string }) {\n this.timestamp = data.timestamp;\n this.largeNumber = data.largeNumber;\n this.label = data.label;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH VALIDATION\n// ============================================================================\n\n/**\n * Entity with property-level validators\n * Features: String validators (minLength, maxLength, pattern)\n */\n@Entity()\nexport class ValidatedEntity {\n @StringProperty({\n minLength: 3,\n maxLength: 20,\n })\n username!: string;\n\n @StringProperty({\n pattern: /^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$/i,\n })\n email!: string;\n\n @NumberProperty({ min: 0, max: 150 })\n age!: number;\n\n constructor(data: { username: string; email: string; age: number }) {\n this.username = data.username;\n this.email = data.email;\n this.age = data.age;\n }\n}\n\n/**\n * Entity with cross-property validation\n * Features: @EntityValidator decorator\n */\n@Entity()\nexport class CrossValidatedEntity {\n @StringProperty() password!: string;\n @StringProperty() confirmPassword!: string;\n @DateProperty() startDate!: Date;\n @DateProperty() endDate!: Date;\n\n constructor(data: {\n password: string;\n confirmPassword: string;\n startDate: Date;\n endDate: Date;\n }) {\n this.password = data.password;\n this.confirmPassword = data.confirmPassword;\n this.startDate = data.startDate;\n this.endDate = data.endDate;\n }\n\n @EntityValidator()\n validatePasswords(): Problem[] {\n if (this.password !== this.confirmPassword) {\n return [\n new Problem({\n property: 'confirmPassword',\n message: 'Passwords do not match',\n }),\n ];\n }\n return [];\n }\n\n @EntityValidator()\n validateDates(): Problem[] {\n if (this.startDate >= this.endDate) {\n return [\n new Problem({\n property: 'endDate',\n message: 'End date must be after start date',\n }),\n ];\n }\n return [];\n }\n}\n\n// ============================================================================\n// ENTITIES WITH OPTIONAL/REQUIRED FIELDS\n// ============================================================================\n\n/**\n * Entity with mix of optional and required properties\n * Features: optional flag\n */\n@Entity()\nexport class OptionalFieldsEntity {\n @StringProperty() requiredField!: string;\n @StringProperty({ optional: true }) optionalField?: string;\n @NumberProperty({ optional: true }) optionalNumber?: number;\n @BooleanProperty() requiredBoolean!: boolean;\n\n constructor(data: {\n requiredField: string;\n optionalField?: string;\n optionalNumber?: number;\n requiredBoolean: boolean;\n }) {\n this.requiredField = data.requiredField;\n this.optionalField = data.optionalField;\n this.optionalNumber = data.optionalNumber;\n this.requiredBoolean = data.requiredBoolean;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH DEFAULT VALUES\n// ============================================================================\n\nlet factoryCallCount = 0;\n\n/**\n * Entity with various default value strategies\n * Features: Static defaults, factory defaults, async factory defaults\n */\n@Entity()\nexport class EntityWithDefaults {\n @StringProperty({ default: 'default-name' })\n name!: string;\n\n @NumberProperty({ default: () => factoryCallCount++ })\n counter!: number;\n\n @DateProperty({ default: () => new Date('2025-01-01') })\n timestamp!: Date;\n\n @StringProperty({ default: async () => 'async-value' })\n asyncField!: string;\n\n @BooleanProperty({ default: true })\n enabled!: boolean;\n\n constructor(data: {\n name?: string;\n counter?: number;\n timestamp?: Date;\n asyncField?: string;\n enabled?: boolean;\n }) {\n this.name = data.name!;\n this.counter = data.counter!;\n this.timestamp = data.timestamp!;\n this.asyncField = data.asyncField!;\n this.enabled = data.enabled!;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH ARRAYS\n// ============================================================================\n\n/**\n * Entity with various array configurations\n * Features: Regular arrays, sparse arrays, array validators\n */\n@Entity()\nexport class EntityWithArrays {\n @ArrayProperty(() => String)\n tags!: string[];\n\n @ArrayProperty(() => Number, {\n minLength: 1,\n maxLength: 5,\n })\n ratings!: number[];\n\n @ArrayProperty(() => String, { sparse: true })\n sparseArray!: (string | null | undefined)[];\n\n @ArrayProperty(() => TestUser)\n users!: TestUser[];\n\n constructor(data: {\n tags: string[];\n ratings: number[];\n sparseArray: (string | null | undefined)[];\n users: TestUser[];\n }) {\n this.tags = data.tags;\n this.ratings = data.ratings;\n this.sparseArray = data.sparseArray;\n this.users = data.users;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH ENUMS\n// ============================================================================\n\nexport enum UserRole {\n ADMIN = 'admin',\n USER = 'user',\n GUEST = 'guest',\n}\n\nexport enum ProductStatus {\n DRAFT = 'draft',\n PUBLISHED = 'published',\n ARCHIVED = 'archived',\n}\n\n/**\n * Entity with enum properties\n * Features: EnumProperty decorator\n */\n@Entity()\nexport class EntityWithEnum {\n @StringProperty() name!: string;\n @EnumProperty(UserRole) role!: UserRole;\n @EnumProperty(ProductStatus) status!: ProductStatus;\n\n constructor(data: { name: string; role: UserRole; status: ProductStatus }) {\n this.name = data.name;\n this.role = data.role;\n this.status = data.status;\n }\n}\n\n// ============================================================================\n// NESTED ENTITIES (2-3 LEVELS)\n// ============================================================================\n\n/**\n * Level 1: Simple address entity\n * Features: Basic nested entity\n */\n@Entity()\nexport class TestAddress {\n @StringProperty() street!: string;\n @StringProperty() city!: string;\n @StringProperty() country!: string;\n @IntProperty() zipCode!: number;\n\n constructor(data: {\n street: string;\n city: string;\n country: string;\n zipCode: number;\n }) {\n this.street = data.street;\n this.city = data.city;\n this.country = data.country;\n this.zipCode = data.zipCode;\n }\n}\n\n/**\n * Level 2: Company with nested address\n * Features: 1-level nesting\n */\n@Entity()\nexport class TestCompany {\n @StringProperty() name!: string;\n @EntityProperty(() => TestAddress) address!: TestAddress;\n @IntProperty() employeeCount!: number;\n\n constructor(data: {\n name: string;\n address: TestAddress;\n employeeCount: number;\n }) {\n this.name = data.name;\n this.address = data.address;\n this.employeeCount = data.employeeCount;\n }\n}\n\n/**\n * Level 3: Employee with nested company (which has nested address)\n * Features: 2-level nesting\n */\n@Entity()\nexport class TestEmployee {\n @StringProperty() name!: string;\n @StringProperty() email!: string;\n @EntityProperty(() => TestCompany) company!: TestCompany;\n @NumberProperty() salary!: number;\n @DateProperty() hireDate!: Date;\n\n constructor(data: {\n name: string;\n email: string;\n company: TestCompany;\n salary: number;\n hireDate: Date;\n }) {\n this.name = data.name;\n this.email = data.email;\n this.company = data.company;\n this.salary = data.salary;\n this.hireDate = data.hireDate;\n }\n}\n\n/**\n * Entity with optional nested entities\n * Features: Optional nested entities\n */\n@Entity()\nexport class EntityWithOptionalNested {\n @StringProperty() id!: string;\n @EntityProperty(() => TestAddress, { optional: true })\n billingAddress?: TestAddress;\n @EntityProperty(() => TestAddress, { optional: true })\n shippingAddress?: TestAddress;\n\n constructor(data: {\n id: string;\n billingAddress?: TestAddress;\n shippingAddress?: TestAddress;\n }) {\n this.id = data.id;\n this.billingAddress = data.billingAddress;\n this.shippingAddress = data.shippingAddress;\n }\n}\n\n// ============================================================================\n// COLLECTION ENTITIES\n// ============================================================================\n\n/**\n * Collection entity wrapping string array\n * Features: @CollectionEntity decorator, unwraps to array\n */\n@CollectionEntity()\nexport class TestTags {\n @ArrayProperty(() => String)\n readonly collection: string[];\n\n constructor(data: { collection: string[] }) {\n this.collection = data.collection;\n }\n}\n\n/**\n * Collection entity wrapping number array\n * Features: @CollectionEntity with numbers\n */\n@CollectionEntity()\nexport class TestIdList {\n @ArrayProperty(() => Number)\n readonly collection: number[];\n\n constructor(data: { collection: number[] }) {\n this.collection = data.collection;\n }\n}\n\n/**\n * Collection entity with entity items\n * Features: @CollectionEntity with nested entities\n */\n@CollectionEntity()\nexport class TestUserCollection {\n @ArrayProperty(() => TestUser)\n readonly collection: TestUser[];\n\n constructor(data: { collection: TestUser[] }) {\n this.collection = data.collection;\n }\n}\n\n// ============================================================================\n// STRINGIFIABLE ENTITIES\n// ============================================================================\n\n/**\n * Stringifiable entity for user IDs\n * Features: @Stringifiable decorator, unwraps to string\n */\n@Stringifiable()\nexport class TestUserId {\n @StringProperty() readonly value: string;\n\n constructor(data: { value: string }) {\n this.value = data.value;\n }\n}\n\n/**\n * Stringifiable entity for emails with validation\n * Features: @Stringifiable with validation\n */\n@Stringifiable()\nexport class TestEmail {\n @StringProperty({\n pattern: /^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$/i,\n })\n readonly value: string;\n\n constructor(data: { value: string }) {\n this.value = data.value;\n }\n}\n\n/**\n * Entity using stringifiable properties\n * Features: Properties that are stringifiable entities\n */\n@Entity()\nexport class EntityWithStringifiable {\n @EntityProperty(() => TestUserId) userId!: TestUserId;\n @EntityProperty(() => TestEmail) email!: TestEmail;\n @StringProperty() name!: string;\n\n constructor(data: { userId: TestUserId; email: TestEmail; name: string }) {\n this.userId = data.userId;\n this.email = data.email;\n this.name = data.name;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH DEPENDENCY INJECTION\n// ============================================================================\n\nexport interface ILogger {\n log(message: string): void;\n}\n\nexport const LOGGER_TOKEN = Symbol('Logger');\n\n/**\n * Entity with injected properties\n * Features: @InjectedProperty decorator\n */\n@Entity()\nexport class EntityWithDI {\n @StringProperty() name!: string;\n @InjectedProperty(LOGGER_TOKEN) logger!: ILogger;\n\n constructor(data: { name: string; logger?: ILogger }) {\n this.name = data.name;\n if (data.logger) {\n this.logger = data.logger;\n }\n }\n\n logName(): void {\n this.logger.log(`Name is: ${this.name}`);\n }\n}\n\n// ============================================================================\n// ENTITIES WITH PASSTHROUGH\n// ============================================================================\n\n/**\n * Entity with passthrough properties\n * Features: @PassthroughProperty for unknown types\n */\n@Entity()\nexport class EntityWithPassthrough {\n @StringProperty() id!: string;\n @PassthroughProperty() metadata!: Record<string, unknown>;\n @PassthroughProperty() config!: unknown;\n\n constructor(data: {\n id: string;\n metadata: Record<string, unknown>;\n config: unknown;\n }) {\n this.id = data.id;\n this.metadata = data.metadata;\n this.config = data.config;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH CUSTOM SERIALIZATION\n// ============================================================================\n\n/**\n * Custom serializable class\n */\nexport class CustomValue {\n constructor(\n public x: number,\n public y: number,\n ) {}\n\n toData() {\n return { x: this.x, y: this.y };\n }\n\n static fromData(data: { x: number; y: number }): CustomValue {\n return new CustomValue(data.x, data.y);\n }\n}\n\n/**\n * Entity with custom serialize/deserialize\n * Features: Custom serialization functions\n */\n@Entity()\nexport class EntityWithCustomSerialization {\n @StringProperty() name!: string;\n\n @Property({\n type: () => CustomValue,\n serialize: (v: CustomValue) => v.toData(),\n deserialize: (d: unknown) =>\n CustomValue.fromData(d as { x: number; y: number }),\n })\n position!: CustomValue;\n\n constructor(data: { name: string; position: CustomValue }) {\n this.name = data.name;\n this.position = data.position;\n }\n}\n\n/**\n * Custom class with equals method\n */\nexport class CustomPoint {\n constructor(\n public x: number,\n public y: number,\n ) {}\n\n equals(other: CustomPoint): boolean {\n return this.x === other.x && this.y === other.y;\n }\n\n toString(): string {\n return `${this.x},${this.y}`;\n }\n\n static fromString(str: string): CustomPoint {\n const [x, y] = str.split(',').map(Number);\n return new CustomPoint(x, y);\n }\n}\n\n/**\n * Entity with custom equals function\n * Features: Custom equality comparison\n */\n@Entity()\nexport class EntityWithCustomEquals {\n @StringProperty() id!: string;\n\n @Property({\n type: () => CustomPoint,\n serialize: (v: CustomPoint) => v.toString(),\n deserialize: (d: unknown) => CustomPoint.fromString(d as string),\n equals: (a: CustomPoint, b: CustomPoint) => a.equals(b),\n })\n location!: CustomPoint;\n\n constructor(data: { id: string; location: CustomPoint }) {\n this.id = data.id;\n this.location = data.location;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH SERIALIZABLE/PARSEABLE PROPERTIES\n// ============================================================================\n\n/**\n * Custom class implementing Serializable interface\n */\nexport class SerializableValue {\n constructor(public data: string) {}\n\n toJSON(): string {\n return this.data;\n }\n\n equals(other: SerializableValue): boolean {\n return this.data === other.data;\n }\n\n static parse(json: unknown): SerializableValue {\n return new SerializableValue(json as string);\n }\n}\n\n/**\n * Entity using SerializableProperty\n * Features: @SerializableProperty decorator\n */\n@Entity()\nexport class EntityWithSerializable {\n @StringProperty() name!: string;\n @SerializableProperty(() => SerializableValue)\n value!: SerializableValue;\n\n constructor(data: { name: string; value: SerializableValue }) {\n this.name = data.name;\n this.value = data.value;\n }\n}\n\n/**\n * Custom class implementing Parseable interface\n */\nexport class ParseableValue {\n constructor(public data: number) {}\n\n toString(): string {\n return String(this.data);\n }\n\n equals(other: ParseableValue): boolean {\n return this.data === other.data;\n }\n\n static parse(str: string): ParseableValue {\n return new ParseableValue(Number(str));\n }\n}\n\n/**\n * Entity using StringifiableProperty\n * Features: @StringifiableProperty decorator\n */\n@Entity()\nexport class EntityWithParseable {\n @StringProperty() label!: string;\n @StringifiableProperty(() => ParseableValue)\n value!: ParseableValue;\n\n constructor(data: { label: string; value: ParseableValue }) {\n this.label = data.label;\n this.value = data.value;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH ZOD VALIDATION\n// ============================================================================\n\nconst emailSchema = z.string().email();\nconst positiveIntSchema = z.number().int().positive();\n\n/**\n * Entity with Zod validation\n * Features: @ZodProperty decorator\n */\n@Entity()\nexport class EntityWithZod {\n @ZodProperty(z.string().min(3).max(20))\n username!: string;\n\n @ZodProperty(emailSchema)\n email!: string;\n\n @ZodProperty(positiveIntSchema)\n count!: number;\n\n constructor(data: { username: string; email: string; count: number }) {\n this.username = data.username;\n this.email = data.email;\n this.count = data.count;\n }\n}\n\n// ============================================================================\n// ENTITIES WITH IMMUTABLE PROPERTIES\n// ============================================================================\n\n/**\n * Entity with immutable (preventUpdates) properties\n * Features: preventUpdates flag\n */\n@Entity()\nexport class EntityWithImmutable {\n @StringProperty({ preventUpdates: true })\n readonly id: string;\n\n @StringProperty() name!: string;\n\n @DateProperty({ preventUpdates: true })\n readonly createdAt: Date;\n\n @NumberProperty() value!: number;\n\n constructor(data: {\n id: string;\n name: string;\n createdAt: Date;\n value: number;\n }) {\n this.id = data.id;\n this.name = data.name;\n this.createdAt = data.createdAt;\n this.value = data.value;\n }\n}\n\n// ============================================================================\n// COMPLEX ENTITY (COMBINING MULTIPLE FEATURES)\n// ============================================================================\n\n/**\n * Complex entity combining multiple features\n * Features: All common features in one entity\n * - Primitives, enums, nested entities, arrays\n * - Optional fields, defaults, validation\n * - Custom serialization, stringifiable properties\n */\n@Entity()\nexport class ComplexEntity {\n @StringProperty({ preventUpdates: true })\n readonly id: string;\n\n @StringProperty({ minLength: 2, maxLength: 50 })\n name!: string;\n\n @EnumProperty(UserRole)\n role!: UserRole;\n\n @EntityProperty(() => TestUserId)\n userId!: TestUserId;\n\n @EntityProperty(() => TestAddress)\n address!: TestAddress;\n\n @ArrayProperty(() => String, { minLength: 0, maxLength: 10 })\n tags!: string[];\n\n @ArrayProperty(() => TestProduct)\n products!: TestProduct[];\n\n @NumberProperty({ optional: true, min: 0 })\n score?: number;\n\n @DateProperty({ default: () => new Date() })\n createdAt!: Date;\n\n @DateProperty({ optional: true })\n updatedAt?: Date;\n\n @BooleanProperty({ default: true })\n active!: boolean;\n\n @PassthroughProperty()\n metadata!: Record<string, unknown>;\n\n constructor(data: {\n id: string;\n name: string;\n role: UserRole;\n userId: TestUserId;\n address: TestAddress;\n tags: string[];\n products: TestProduct[];\n score?: number;\n createdAt?: Date;\n updatedAt?: Date;\n active?: boolean;\n metadata: Record<string, unknown>;\n }) {\n this.id = data.id;\n this.name = data.name;\n this.role = data.role;\n this.userId = data.userId;\n this.address = data.address;\n this.tags = data.tags;\n this.products = data.products;\n this.score = data.score;\n this.createdAt = data.createdAt!;\n this.updatedAt = data.updatedAt;\n this.active = data.active!;\n this.metadata = data.metadata;\n }\n\n @EntityValidator()\n validateProducts(): Problem[] {\n if (this.products.length === 0 && this.active) {\n return [\n new Problem({\n property: 'products',\n message: 'Active entity must have at least one product',\n }),\n ];\n }\n return [];\n }\n}\n\n// ============================================================================\n// HELPER TO RESET FACTORY COUNTER (FOR TESTING)\n// ============================================================================\n\nexport function resetFactoryCallCount(): void {\n factoryCallCount = 0;\n}\n"],"names":["z","Entity","CollectionEntity","Stringifiable","EntityValidator","Property","StringProperty","NumberProperty","IntProperty","BooleanProperty","DateProperty","BigIntProperty","EnumProperty","EntityProperty","ArrayProperty","PassthroughProperty","SerializableProperty","StringifiableProperty","InjectedProperty","ZodProperty","Problem","TestUser","data","name","age","active","TestProduct","id","price","quantity","createdAt","EntityWithSpecialTypes","timestamp","largeNumber","label","ValidatedEntity","username","email","minLength","maxLength","pattern","min","max","CrossValidatedEntity","password","confirmPassword","startDate","endDate","validatePasswords","property","message","validateDates","OptionalFieldsEntity","requiredField","optionalField","optionalNumber","requiredBoolean","optional","factoryCallCount","EntityWithDefaults","counter","asyncField","enabled","default","Date","EntityWithArrays","tags","ratings","sparseArray","users","String","Number","sparse","UserRole","ProductStatus","EntityWithEnum","role","status","TestAddress","street","city","country","zipCode","TestCompany","address","employeeCount","TestEmployee","company","salary","hireDate","EntityWithOptionalNested","billingAddress","shippingAddress","TestTags","collection","TestIdList","TestUserCollection","TestUserId","value","TestEmail","EntityWithStringifiable","userId","LOGGER_TOKEN","Symbol","EntityWithDI","logger","logName","log","EntityWithPassthrough","metadata","config","CustomValue","x","y","toData","fromData","EntityWithCustomSerialization","position","type","serialize","v","deserialize","d","CustomPoint","equals","other","toString","fromString","str","split","map","EntityWithCustomEquals","location","a","b","SerializableValue","toJSON","parse","json","EntityWithSerializable","ParseableValue","EntityWithParseable","emailSchema","string","positiveIntSchema","number","int","positive","EntityWithZod","count","EntityWithImmutable","preventUpdates","ComplexEntity","products","score","updatedAt","validateProducts","length","resetFactoryCallCount"],"mappings":"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"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export interface PropertyOptions<T = any, C extends CtorLike<T> = AnyCtor<T> | B
|
|
|
52
52
|
/**
|
|
53
53
|
* Type constructor for this property. Required for EntityUtils.parse() support.
|
|
54
54
|
* Use a function that returns the type constructor to support forward references.
|
|
55
|
+
* Not required for discriminated entity properties nor passthrough properties.
|
|
55
56
|
* @example
|
|
56
57
|
* @Property({ type: () => String })
|
|
57
58
|
* name!: string;
|
|
@@ -59,7 +60,7 @@ export interface PropertyOptions<T = any, C extends CtorLike<T> = AnyCtor<T> | B
|
|
|
59
60
|
* @Property({ type: () => Address })
|
|
60
61
|
* address!: Address;
|
|
61
62
|
*/
|
|
62
|
-
type
|
|
63
|
+
type?: () => C;
|
|
63
64
|
/**
|
|
64
65
|
* Whether this property is an array. Defaults to false.
|
|
65
66
|
* When true, the deserializer will map over array elements.
|
|
@@ -183,6 +184,25 @@ export interface PropertyOptions<T = any, C extends CtorLike<T> = AnyCtor<T> | B
|
|
|
183
184
|
* scores!: number[];
|
|
184
185
|
*/
|
|
185
186
|
arrayValidators?: PropertyValidator<InstanceOfCtorLike<C>[]>[];
|
|
187
|
+
/**
|
|
188
|
+
* Indicates this property uses discriminated entity types.
|
|
189
|
+
* The discriminator property name (e.g., '__type') is used to determine the entity type at runtime.
|
|
190
|
+
* When true, serialization will include the discriminator inline with the entity.
|
|
191
|
+
* During deserialization, the discriminator value is used to lookup the entity class in EntityRegistry.
|
|
192
|
+
* @example
|
|
193
|
+
* @DiscriminatedEntityProperty({ discriminatorProperty: '__type' })
|
|
194
|
+
* item!: BaseItem; // Could be ItemA or ItemB at runtime
|
|
195
|
+
*/
|
|
196
|
+
discriminated?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* The property name to use as the discriminator for discriminated entity properties.
|
|
199
|
+
* Defaults to '__type' if not specified.
|
|
200
|
+
* Only applicable when discriminated is true.
|
|
201
|
+
* @example
|
|
202
|
+
* @DiscriminatedEntityProperty({ discriminatorProperty: 'entityType' })
|
|
203
|
+
* item!: BaseItem;
|
|
204
|
+
*/
|
|
205
|
+
discriminatorProperty?: string;
|
|
186
206
|
}
|
|
187
207
|
/**
|
|
188
208
|
* A validator function for a property.
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,qBAAqB,eAA8B,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,eAA4B,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,2BAA2B,eAAoC,CAAC;AAE7E;;GAEG;AACH,eAAO,MAAM,6BAA6B,eAEzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,eAE1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sCAAsC,eAElD,CAAC;AAEF,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,GAAG;IAAE,SAAS,EAAE,CAAC,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,CAAC;AAEpB,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;AAEpD,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,SAAS,iBAAiB,GAC3D,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,kBAAkB,GAC1B,OAAO,GACP,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,iBAAiB,GACzB,MAAM,GACN,CAAC,SAAS,eAAe,GACvB,IAAI,GACJ,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,CAAC,GACD,KAAK,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,eAAe,CAC9B,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY;IAEjD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAEzE
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-wrapper-object-types */\nimport type { Problem } from './problem.js';\n\n/**\n * Metadata key used to store property information\n */\nexport const PROPERTY_METADATA_KEY = Symbol('property:metadata');\n\n/**\n * Metadata key used to store property options\n */\nexport const PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'property:options:metadata',\n);\n\n/**\n * Metadata key used to store entity information\n */\nexport const ENTITY_METADATA_KEY = Symbol('entity:metadata');\n\n/**\n * Metadata key used to store entity options\n */\nexport const ENTITY_OPTIONS_METADATA_KEY = Symbol('entity:options:metadata');\n\n/**\n * Metadata key used to store entity validator methods\n */\nexport const ENTITY_VALIDATOR_METADATA_KEY = Symbol(\n 'entity:validator:metadata',\n);\n\n/**\n * Metadata key used to store injected property information\n */\nexport const INJECTED_PROPERTY_METADATA_KEY = Symbol(\n 'injected-property:metadata',\n);\n\n/**\n * Metadata key used to store injected property options (tokens)\n */\nexport const INJECTED_PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'injected-property:options:metadata',\n);\n\nexport type AnyCtor<T = any> = Function & { prototype: T };\n\nexport type BuiltinCtors =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | SymbolConstructor\n | DateConstructor;\n\n/**\n * Type constructors for primitive types that can be deserialized\n * (excludes Symbol which cannot be deserialized from JSON)\n */\nexport type PrimitiveConstructor =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | DateConstructor;\n\nexport type CtorLike<T> = AnyCtor<T> | BuiltinCtors;\n\nexport type InstanceOfCtorLike<C> = C extends StringConstructor\n ? string\n : C extends NumberConstructor\n ? number\n : C extends BooleanConstructor\n ? boolean\n : C extends BigIntConstructor\n ? bigint\n : C extends SymbolConstructor\n ? symbol\n : C extends DateConstructor\n ? Date\n : C extends AnyCtor<infer T>\n ? T\n : never;\n\n/**\n * Options for the Property decorator\n */\nexport interface PropertyOptions<\n T = any,\n C extends CtorLike<T> = AnyCtor<T> | BuiltinCtors,\n> {\n /**\n * Custom equality comparison function for this property\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns true if values are equal, false otherwise\n */\n equals?: (a: InstanceOfCtorLike<C>, b: InstanceOfCtorLike<C>) => boolean;\n\n /**\n * Type constructor for this property. Required for EntityUtils.parse() support.\n * Use a function that returns the type constructor to support forward references.\n * @example\n * @Property({ type: () => String })\n * name!: string;\n *\n * @Property({ type: () => Address })\n * address!: Address;\n */\n type: () => C;\n\n /**\n * Whether this property is an array. Defaults to false.\n * When true, the deserializer will map over array elements.\n * @example\n * @Property({ type: () => String, array: true })\n * tags!: string[];\n */\n array?: boolean;\n\n /**\n * Whether this property is optional. Defaults to false.\n * When true, the property can be undefined or null.\n * When false, the property must be present and not null/undefined.\n * @example\n * @Property({ type: () => String, optional: true })\n * nickname?: string;\n */\n optional?: boolean;\n\n /**\n * Whether the array can contain null/undefined elements. Defaults to false.\n * Only applicable when array is true.\n * When false (default), null/undefined elements will cause an error.\n * When true, null/undefined elements are allowed in the array.\n * @example\n * @Property({ type: () => String, array: true, sparse: true })\n * tags!: (string | null)[];\n */\n sparse?: boolean;\n\n /**\n * Whether to bypass type validation and pass values through as-is.\n * Use this for generic types like Record<string, unknown> or any.\n * When true, no type checking or transformation is performed.\n * Also bypasses any custom serialize/deserialize callbacks.\n * @example\n * @Property({ passthrough: true })\n * metadata!: Record<string, unknown>;\n */\n passthrough?: boolean;\n\n /**\n * Whether to prevent this property from being updated via EntityUtils.update().\n * When true, this property cannot be modified through update operations.\n * Defaults to false, allowing the property to be updated.\n * @example\n * @Property({ type: () => String, preventUpdates: true })\n * id!: string; // This property cannot be updated\n */\n preventUpdates?: boolean;\n\n /**\n * Default value for the property when not provided during deserialization.\n * Can be a static value or a function that returns the default value.\n * The function can be async and return a Promise.\n * @example\n * @Property({ type: () => String, default: 'N/A' })\n * nickname?: string;\n *\n * @Property({ type: () => Date, default: () => new Date() })\n * createdAt!: Date;\n *\n * @Property({ type: () => String, default: async () => await fetchDefaultValue() })\n * value!: string;\n */\n default?:\n | InstanceOfCtorLike<C>\n | (() => InstanceOfCtorLike<C> | Promise<InstanceOfCtorLike<C>>);\n\n /**\n * Custom serialization function to convert the property value to JSON-compatible format.\n * Must be paired with deserialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n serialize?: (value: InstanceOfCtorLike<C>) => unknown;\n\n /**\n * Custom deserialization function to convert JSON data back to the property type.\n * Must be paired with serialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n deserialize?: (serialized: unknown) => InstanceOfCtorLike<C>;\n\n /**\n * Array of validator functions for this property.\n * Each validator receives the property value and validation context.\n * Empty array means validation passed.\n * If the property is an array (array: true), these validators will run against each item.\n * Use arrayValidators instead to validate the array as a whole.\n * If passthrough is true, validators will run against the raw value.\n * @example\n * @Property({\n * type: () => String,\n * validators: [\n * (value, { createProblem }) =>\n * value.length > 10 ? [createProblem('Too long')] : []\n * ]\n * })\n * name!: string;\n */\n validators?: PropertyValidator<InstanceOfCtorLike<C>>[];\n\n /**\n * Array of validator functions for this property when it is an array.\n * Each validator receives the array value and validation context.\n * Empty array means validation passed.\n * Only applicable when array is true.\n * Not applicable when passthrough is true.\n * @example\n * @Property({\n * type: () => Number,\n * array: true,\n * arrayValidators: [\n * (value, { createProblem }) =>\n * value.length === 0 ? [createProblem('Array cannot be empty')] : []\n * ]\n * })\n * scores!: number[];\n */\n arrayValidators?: PropertyValidator<InstanceOfCtorLike<C>[]>[];\n}\n\n/**\n * A validator function for a property.\n * The validator receives the value and returns Problems with property paths relative to the value.\n * Can be synchronous or asynchronous.\n * The calling code will prepend the actual property key to all returned problems.\n *\n * @param data - Object containing the value to validate\n * @param data.value - The value to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems.\n * Problems should have empty property for the value itself,\n * or relative paths for nested properties (e.g., 'name', '[0]', 'address.street')\n *\n * @example\n * ```typescript\n * // Synchronous validator\n * (({ value }) =>\n * value.length < 3 ? [new Problem({ property: '', message: 'Too short' })] : [])\n *\n * // Asynchronous validator\n * async ({ value }) => {\n * const exists = await checkDatabase(value);\n * return exists ? [] : [new Problem({ property: '', message: 'Not found' })];\n * }\n * ```\n */\nexport type PropertyValidator<T> = (data: {\n value: T;\n}) => Problem[] | Promise<Problem[]>;\n\n/**\n * A validator function for an entity.\n * Can be synchronous or asynchronous.\n * @param instance - The entity instance to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems\n */\nexport type EntityValidatorFn<T = any> = (\n instance: T,\n) => Problem[] | Promise<Problem[]>;\n\nexport interface Type<T = any> extends Function {\n new (...args: any[]): T;\n}\n\nexport type EntityDIToken<T = any> =\n | string\n | symbol\n | Function\n | AnyCtor<T>\n | Type<T>;\n\nexport type EntityDIProvider<T = any> =\n | {\n provide: EntityDIToken<T>;\n useValue?: T;\n useFactory?: never;\n }\n | {\n provide: EntityDIToken<T>;\n useValue?: never;\n useFactory?: () => T | Promise<T>;\n };\n\nexport type EntityDIFallbackFn = (token: EntityDIToken) => Promise<any>;\n\n/**\n * Generic type for safe operation results that can succeed or fail\n * @template T - The data type on success\n */\nexport type SafeOperationResult<T> = Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n>;\n\nexport type ParseOptions = { strict?: boolean };\n"],"names":["PROPERTY_METADATA_KEY","Symbol","PROPERTY_OPTIONS_METADATA_KEY","ENTITY_METADATA_KEY","ENTITY_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","INJECTED_PROPERTY_METADATA_KEY","INJECTED_PROPERTY_OPTIONS_METADATA_KEY"],"mappings":"AAAA,6DAA6D,GAC7D,qDAAqD,GACrD,6DAA6D,GAG7D;;CAEC,GACD,OAAO,MAAMA,wBAAwBC,OAAO,qBAAqB;AAEjE;;CAEC,GACD,OAAO,MAAMC,gCAAgCD,OAC3C,6BACA;AAEF;;CAEC,GACD,OAAO,MAAME,sBAAsBF,OAAO,mBAAmB;AAE7D;;CAEC,GACD,OAAO,MAAMG,8BAA8BH,OAAO,2BAA2B;AAE7E;;CAEC,GACD,OAAO,MAAMI,gCAAgCJ,OAC3C,6BACA;AAEF;;CAEC,GACD,OAAO,MAAMK,iCAAiCL,OAC5C,8BACA;AAEF;;CAEC,GACD,OAAO,MAAMM,yCAAyCN,OACpD,sCACA"}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-wrapper-object-types */\nimport type { Problem } from './problem.js';\n\n/**\n * Metadata key used to store property information\n */\nexport const PROPERTY_METADATA_KEY = Symbol('property:metadata');\n\n/**\n * Metadata key used to store property options\n */\nexport const PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'property:options:metadata',\n);\n\n/**\n * Metadata key used to store entity information\n */\nexport const ENTITY_METADATA_KEY = Symbol('entity:metadata');\n\n/**\n * Metadata key used to store entity options\n */\nexport const ENTITY_OPTIONS_METADATA_KEY = Symbol('entity:options:metadata');\n\n/**\n * Metadata key used to store entity validator methods\n */\nexport const ENTITY_VALIDATOR_METADATA_KEY = Symbol(\n 'entity:validator:metadata',\n);\n\n/**\n * Metadata key used to store injected property information\n */\nexport const INJECTED_PROPERTY_METADATA_KEY = Symbol(\n 'injected-property:metadata',\n);\n\n/**\n * Metadata key used to store injected property options (tokens)\n */\nexport const INJECTED_PROPERTY_OPTIONS_METADATA_KEY = Symbol(\n 'injected-property:options:metadata',\n);\n\nexport type AnyCtor<T = any> = Function & { prototype: T };\n\nexport type BuiltinCtors =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | SymbolConstructor\n | DateConstructor;\n\n/**\n * Type constructors for primitive types that can be deserialized\n * (excludes Symbol which cannot be deserialized from JSON)\n */\nexport type PrimitiveConstructor =\n | StringConstructor\n | NumberConstructor\n | BooleanConstructor\n | BigIntConstructor\n | DateConstructor;\n\nexport type CtorLike<T> = AnyCtor<T> | BuiltinCtors;\n\nexport type InstanceOfCtorLike<C> = C extends StringConstructor\n ? string\n : C extends NumberConstructor\n ? number\n : C extends BooleanConstructor\n ? boolean\n : C extends BigIntConstructor\n ? bigint\n : C extends SymbolConstructor\n ? symbol\n : C extends DateConstructor\n ? Date\n : C extends AnyCtor<infer T>\n ? T\n : never;\n\n/**\n * Options for the Property decorator\n */\nexport interface PropertyOptions<\n T = any,\n C extends CtorLike<T> = AnyCtor<T> | BuiltinCtors,\n> {\n /**\n * Custom equality comparison function for this property\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns true if values are equal, false otherwise\n */\n equals?: (a: InstanceOfCtorLike<C>, b: InstanceOfCtorLike<C>) => boolean;\n\n /**\n * Type constructor for this property. Required for EntityUtils.parse() support.\n * Use a function that returns the type constructor to support forward references.\n * Not required for discriminated entity properties nor passthrough properties.\n * @example\n * @Property({ type: () => String })\n * name!: string;\n *\n * @Property({ type: () => Address })\n * address!: Address;\n */\n type?: () => C;\n\n /**\n * Whether this property is an array. Defaults to false.\n * When true, the deserializer will map over array elements.\n * @example\n * @Property({ type: () => String, array: true })\n * tags!: string[];\n */\n array?: boolean;\n\n /**\n * Whether this property is optional. Defaults to false.\n * When true, the property can be undefined or null.\n * When false, the property must be present and not null/undefined.\n * @example\n * @Property({ type: () => String, optional: true })\n * nickname?: string;\n */\n optional?: boolean;\n\n /**\n * Whether the array can contain null/undefined elements. Defaults to false.\n * Only applicable when array is true.\n * When false (default), null/undefined elements will cause an error.\n * When true, null/undefined elements are allowed in the array.\n * @example\n * @Property({ type: () => String, array: true, sparse: true })\n * tags!: (string | null)[];\n */\n sparse?: boolean;\n\n /**\n * Whether to bypass type validation and pass values through as-is.\n * Use this for generic types like Record<string, unknown> or any.\n * When true, no type checking or transformation is performed.\n * Also bypasses any custom serialize/deserialize callbacks.\n * @example\n * @Property({ passthrough: true })\n * metadata!: Record<string, unknown>;\n */\n passthrough?: boolean;\n\n /**\n * Whether to prevent this property from being updated via EntityUtils.update().\n * When true, this property cannot be modified through update operations.\n * Defaults to false, allowing the property to be updated.\n * @example\n * @Property({ type: () => String, preventUpdates: true })\n * id!: string; // This property cannot be updated\n */\n preventUpdates?: boolean;\n\n /**\n * Default value for the property when not provided during deserialization.\n * Can be a static value or a function that returns the default value.\n * The function can be async and return a Promise.\n * @example\n * @Property({ type: () => String, default: 'N/A' })\n * nickname?: string;\n *\n * @Property({ type: () => Date, default: () => new Date() })\n * createdAt!: Date;\n *\n * @Property({ type: () => String, default: async () => await fetchDefaultValue() })\n * value!: string;\n */\n default?:\n | InstanceOfCtorLike<C>\n | (() => InstanceOfCtorLike<C> | Promise<InstanceOfCtorLike<C>>);\n\n /**\n * Custom serialization function to convert the property value to JSON-compatible format.\n * Must be paired with deserialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n serialize?: (value: InstanceOfCtorLike<C>) => unknown;\n\n /**\n * Custom deserialization function to convert JSON data back to the property type.\n * Must be paired with serialize - both must be defined together or both omitted.\n * Not used when passthrough is true.\n * @example\n * @Property({\n * type: () => MyClass,\n * serialize: (value) => ({ data: value.toData() }),\n * deserialize: (json) => MyClass.fromData(json.data)\n * })\n * myProperty!: MyClass;\n */\n deserialize?: (serialized: unknown) => InstanceOfCtorLike<C>;\n\n /**\n * Array of validator functions for this property.\n * Each validator receives the property value and validation context.\n * Empty array means validation passed.\n * If the property is an array (array: true), these validators will run against each item.\n * Use arrayValidators instead to validate the array as a whole.\n * If passthrough is true, validators will run against the raw value.\n * @example\n * @Property({\n * type: () => String,\n * validators: [\n * (value, { createProblem }) =>\n * value.length > 10 ? [createProblem('Too long')] : []\n * ]\n * })\n * name!: string;\n */\n validators?: PropertyValidator<InstanceOfCtorLike<C>>[];\n\n /**\n * Array of validator functions for this property when it is an array.\n * Each validator receives the array value and validation context.\n * Empty array means validation passed.\n * Only applicable when array is true.\n * Not applicable when passthrough is true.\n * @example\n * @Property({\n * type: () => Number,\n * array: true,\n * arrayValidators: [\n * (value, { createProblem }) =>\n * value.length === 0 ? [createProblem('Array cannot be empty')] : []\n * ]\n * })\n * scores!: number[];\n */\n arrayValidators?: PropertyValidator<InstanceOfCtorLike<C>[]>[];\n\n /**\n * Indicates this property uses discriminated entity types.\n * The discriminator property name (e.g., '__type') is used to determine the entity type at runtime.\n * When true, serialization will include the discriminator inline with the entity.\n * During deserialization, the discriminator value is used to lookup the entity class in EntityRegistry.\n * @example\n * @DiscriminatedEntityProperty({ discriminatorProperty: '__type' })\n * item!: BaseItem; // Could be ItemA or ItemB at runtime\n */\n discriminated?: boolean;\n\n /**\n * The property name to use as the discriminator for discriminated entity properties.\n * Defaults to '__type' if not specified.\n * Only applicable when discriminated is true.\n * @example\n * @DiscriminatedEntityProperty({ discriminatorProperty: 'entityType' })\n * item!: BaseItem;\n */\n discriminatorProperty?: string;\n}\n\n/**\n * A validator function for a property.\n * The validator receives the value and returns Problems with property paths relative to the value.\n * Can be synchronous or asynchronous.\n * The calling code will prepend the actual property key to all returned problems.\n *\n * @param data - Object containing the value to validate\n * @param data.value - The value to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems.\n * Problems should have empty property for the value itself,\n * or relative paths for nested properties (e.g., 'name', '[0]', 'address.street')\n *\n * @example\n * ```typescript\n * // Synchronous validator\n * (({ value }) =>\n * value.length < 3 ? [new Problem({ property: '', message: 'Too short' })] : [])\n *\n * // Asynchronous validator\n * async ({ value }) => {\n * const exists = await checkDatabase(value);\n * return exists ? [] : [new Problem({ property: '', message: 'Not found' })];\n * }\n * ```\n */\nexport type PropertyValidator<T> = (data: {\n value: T;\n}) => Problem[] | Promise<Problem[]>;\n\n/**\n * A validator function for an entity.\n * Can be synchronous or asynchronous.\n * @param instance - The entity instance to validate\n * @returns Array of Problems (empty if valid) or Promise resolving to Problems\n */\nexport type EntityValidatorFn<T = any> = (\n instance: T,\n) => Problem[] | Promise<Problem[]>;\n\nexport interface Type<T = any> extends Function {\n new (...args: any[]): T;\n}\n\nexport type EntityDIToken<T = any> =\n | string\n | symbol\n | Function\n | AnyCtor<T>\n | Type<T>;\n\nexport type EntityDIProvider<T = any> =\n | {\n provide: EntityDIToken<T>;\n useValue?: T;\n useFactory?: never;\n }\n | {\n provide: EntityDIToken<T>;\n useValue?: never;\n useFactory?: () => T | Promise<T>;\n };\n\nexport type EntityDIFallbackFn = (token: EntityDIToken) => Promise<any>;\n\n/**\n * Generic type for safe operation results that can succeed or fail\n * @template T - The data type on success\n */\nexport type SafeOperationResult<T> = Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n>;\n\nexport type ParseOptions = { strict?: boolean };\n"],"names":["PROPERTY_METADATA_KEY","Symbol","PROPERTY_OPTIONS_METADATA_KEY","ENTITY_METADATA_KEY","ENTITY_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","INJECTED_PROPERTY_METADATA_KEY","INJECTED_PROPERTY_OPTIONS_METADATA_KEY"],"mappings":"AAAA,6DAA6D,GAC7D,qDAAqD,GACrD,6DAA6D,GAG7D;;CAEC,GACD,OAAO,MAAMA,wBAAwBC,OAAO,qBAAqB;AAEjE;;CAEC,GACD,OAAO,MAAMC,gCAAgCD,OAC3C,6BACA;AAEF;;CAEC,GACD,OAAO,MAAME,sBAAsBF,OAAO,mBAAmB;AAE7D;;CAEC,GACD,OAAO,MAAMG,8BAA8BH,OAAO,2BAA2B;AAE7E;;CAEC,GACD,OAAO,MAAMI,gCAAgCJ,OAC3C,6BACA;AAEF;;CAEC,GACD,OAAO,MAAMK,iCAAiCL,OAC5C,8BACA;AAEF;;CAEC,GACD,OAAO,MAAMM,yCAAyCN,OACpD,sCACA"}
|
|
@@ -35,23 +35,23 @@ export declare function combinePropertyPaths(prefix: string, suffix: string): st
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function createValidationError(message: string): ValidationError;
|
|
37
37
|
/**
|
|
38
|
-
* Prepends a property path to all problems
|
|
38
|
+
* Prepends a property path to all problems.
|
|
39
39
|
* Problems with empty property names get the path directly.
|
|
40
40
|
* Problems starting with '[' get the path without a dot separator.
|
|
41
41
|
* Other problems get the path with a dot separator.
|
|
42
42
|
*
|
|
43
43
|
* @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')
|
|
44
|
-
* @param
|
|
44
|
+
* @param problems - The array of Problems to process
|
|
45
45
|
* @returns Array of Problems with the property path prepended
|
|
46
46
|
*
|
|
47
47
|
* @example
|
|
48
48
|
* ```typescript
|
|
49
|
-
* const
|
|
49
|
+
* const problems = [
|
|
50
50
|
* new Problem({ property: '', message: 'Invalid type' }),
|
|
51
51
|
* new Problem({ property: 'name', message: 'Required' }),
|
|
52
52
|
* new Problem({ property: '[0]', message: 'Invalid element' })
|
|
53
|
-
* ]
|
|
54
|
-
* const
|
|
53
|
+
* ];
|
|
54
|
+
* const result = prependPropertyPath('user', problems);
|
|
55
55
|
* // [
|
|
56
56
|
* // { property: 'user', message: 'Invalid type' },
|
|
57
57
|
* // { property: 'user.name', message: 'Required' },
|
|
@@ -59,7 +59,7 @@ export declare function createValidationError(message: string): ValidationError;
|
|
|
59
59
|
* // ]
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
|
-
export declare function prependPropertyPath(propertyPath: string,
|
|
62
|
+
export declare function prependPropertyPath(propertyPath: string, problems: Problem[]): Problem[];
|
|
63
63
|
/**
|
|
64
64
|
* Prepends an array index to all problems in a ValidationError.
|
|
65
65
|
* Problems with empty property get `[index]` directly.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-utils.d.ts","sourceRoot":"","sources":["../../src/lib/validation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ3E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAOtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,
|
|
1
|
+
{"version":3,"file":"validation-utils.d.ts","sourceRoot":"","sources":["../../src/lib/validation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ3E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAOtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,OAAO,EAAE,GAClB,OAAO,EAAE,CAOX;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,eAAe,GACrB,OAAO,EAAE,CAOX"}
|
|
@@ -48,31 +48,31 @@ import { ValidationError } from './validation-error.js';
|
|
|
48
48
|
]);
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* Prepends a property path to all problems
|
|
51
|
+
* Prepends a property path to all problems.
|
|
52
52
|
* Problems with empty property names get the path directly.
|
|
53
53
|
* Problems starting with '[' get the path without a dot separator.
|
|
54
54
|
* Other problems get the path with a dot separator.
|
|
55
55
|
*
|
|
56
56
|
* @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')
|
|
57
|
-
* @param
|
|
57
|
+
* @param problems - The array of Problems to process
|
|
58
58
|
* @returns Array of Problems with the property path prepended
|
|
59
59
|
*
|
|
60
60
|
* @example
|
|
61
61
|
* ```typescript
|
|
62
|
-
* const
|
|
62
|
+
* const problems = [
|
|
63
63
|
* new Problem({ property: '', message: 'Invalid type' }),
|
|
64
64
|
* new Problem({ property: 'name', message: 'Required' }),
|
|
65
65
|
* new Problem({ property: '[0]', message: 'Invalid element' })
|
|
66
|
-
* ]
|
|
67
|
-
* const
|
|
66
|
+
* ];
|
|
67
|
+
* const result = prependPropertyPath('user', problems);
|
|
68
68
|
* // [
|
|
69
69
|
* // { property: 'user', message: 'Invalid type' },
|
|
70
70
|
* // { property: 'user.name', message: 'Required' },
|
|
71
71
|
* // { property: 'user[0]', message: 'Invalid element' }
|
|
72
72
|
* // ]
|
|
73
73
|
* ```
|
|
74
|
-
*/ export function prependPropertyPath(propertyPath,
|
|
75
|
-
return
|
|
74
|
+
*/ export function prependPropertyPath(propertyPath, problems) {
|
|
75
|
+
return problems.map((problem)=>{
|
|
76
76
|
return new Problem({
|
|
77
77
|
property: combinePropertyPaths(propertyPath, problem.property),
|
|
78
78
|
message: problem.message
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/validation-utils.ts"],"sourcesContent":["import { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\n\n/**\n * Combines a property path prefix with a suffix according to deterministic rules:\n * - If suffix is empty, returns prefix\n * - If suffix starts with '[', concatenates without separator (e.g., 'items' + '[0]' → 'items[0]')\n * - Otherwise, concatenates with dot separator (e.g., 'user' + 'name' → 'user.name')\n *\n * @param prefix - The property path to prepend\n * @param suffix - The property path to append\n * @returns The combined property path\n *\n * @example\n * ```typescript\n * combinePropertyPaths('user', '') // 'user'\n * combinePropertyPaths('user', 'name') // 'user.name'\n * combinePropertyPaths('items', '[0]') // 'items[0]'\n * combinePropertyPaths('[0]', 'name') // '[0].name'\n * ```\n */\nexport function combinePropertyPaths(prefix: string, suffix: string): string {\n if (suffix === '') {\n return prefix;\n }\n if (suffix.startsWith('[')) {\n return `${prefix}${suffix}`;\n }\n return `${prefix}.${suffix}`;\n}\n\n/**\n * Creates a ValidationError with a single problem that has an empty property.\n * This is used when reporting errors at the current scope level, where the caller\n * will prepend the appropriate context path.\n *\n * @param message - The error message\n * @returns A ValidationError with a single problem with empty property\n *\n * @example\n * ```typescript\n * throw createValidationError('Expects a string but received number');\n * // Creates: ValidationError([{ property: '', message: 'Expects a string but received number' }])\n * ```\n */\nexport function createValidationError(message: string): ValidationError {\n return new ValidationError([\n new Problem({\n property: '',\n message,\n }),\n ]);\n}\n\n/**\n * Prepends a property path to all problems
|
|
1
|
+
{"version":3,"sources":["../../src/lib/validation-utils.ts"],"sourcesContent":["import { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\n\n/**\n * Combines a property path prefix with a suffix according to deterministic rules:\n * - If suffix is empty, returns prefix\n * - If suffix starts with '[', concatenates without separator (e.g., 'items' + '[0]' → 'items[0]')\n * - Otherwise, concatenates with dot separator (e.g., 'user' + 'name' → 'user.name')\n *\n * @param prefix - The property path to prepend\n * @param suffix - The property path to append\n * @returns The combined property path\n *\n * @example\n * ```typescript\n * combinePropertyPaths('user', '') // 'user'\n * combinePropertyPaths('user', 'name') // 'user.name'\n * combinePropertyPaths('items', '[0]') // 'items[0]'\n * combinePropertyPaths('[0]', 'name') // '[0].name'\n * ```\n */\nexport function combinePropertyPaths(prefix: string, suffix: string): string {\n if (suffix === '') {\n return prefix;\n }\n if (suffix.startsWith('[')) {\n return `${prefix}${suffix}`;\n }\n return `${prefix}.${suffix}`;\n}\n\n/**\n * Creates a ValidationError with a single problem that has an empty property.\n * This is used when reporting errors at the current scope level, where the caller\n * will prepend the appropriate context path.\n *\n * @param message - The error message\n * @returns A ValidationError with a single problem with empty property\n *\n * @example\n * ```typescript\n * throw createValidationError('Expects a string but received number');\n * // Creates: ValidationError([{ property: '', message: 'Expects a string but received number' }])\n * ```\n */\nexport function createValidationError(message: string): ValidationError {\n return new ValidationError([\n new Problem({\n property: '',\n message,\n }),\n ]);\n}\n\n/**\n * Prepends a property path to all problems.\n * Problems with empty property names get the path directly.\n * Problems starting with '[' get the path without a dot separator.\n * Other problems get the path with a dot separator.\n *\n * @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')\n * @param problems - The array of Problems to process\n * @returns Array of Problems with the property path prepended\n *\n * @example\n * ```typescript\n * const problems = [\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' }),\n * new Problem({ property: '[0]', message: 'Invalid element' })\n * ];\n * const result = prependPropertyPath('user', problems);\n * // [\n * // { property: 'user', message: 'Invalid type' },\n * // { property: 'user.name', message: 'Required' },\n * // { property: 'user[0]', message: 'Invalid element' }\n * // ]\n * ```\n */\nexport function prependPropertyPath(\n propertyPath: string,\n problems: Problem[],\n): Problem[] {\n return problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(propertyPath, problem.property),\n message: problem.message,\n });\n });\n}\n\n/**\n * Prepends an array index to all problems in a ValidationError.\n * Problems with empty property get `[index]` directly.\n * Problems with non-empty property get `[index].property` format.\n *\n * @param index - The array index to prepend\n * @param error - The ValidationError containing problems to process\n * @returns Array of Problems with the array index prepended\n *\n * @example\n * ```typescript\n * const error = new ValidationError([\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' })\n * ]);\n * const problems = prependArrayIndex(0, error);\n * // [\n * // { property: '[0]', message: 'Invalid type' },\n * // { property: '[0].name', message: 'Required' }\n * // ]\n * ```\n */\nexport function prependArrayIndex(\n index: number,\n error: ValidationError,\n): Problem[] {\n return error.problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(`[${index}]`, problem.property),\n message: problem.message,\n });\n });\n}\n"],"names":["Problem","ValidationError","combinePropertyPaths","prefix","suffix","startsWith","createValidationError","message","property","prependPropertyPath","propertyPath","problems","map","problem","prependArrayIndex","index","error"],"mappings":"AAAA,SAASA,OAAO,QAAQ,eAAe;AACvC,SAASC,eAAe,QAAQ,wBAAwB;AAExD;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC,qBAAqBC,MAAc,EAAEC,MAAc;IACjE,IAAIA,WAAW,IAAI;QACjB,OAAOD;IACT;IACA,IAAIC,OAAOC,UAAU,CAAC,MAAM;QAC1B,OAAO,GAAGF,SAASC,QAAQ;IAC7B;IACA,OAAO,GAAGD,OAAO,CAAC,EAAEC,QAAQ;AAC9B;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASE,sBAAsBC,OAAe;IACnD,OAAO,IAAIN,gBAAgB;QACzB,IAAID,QAAQ;YACVQ,UAAU;YACVD;QACF;KACD;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASE,oBACdC,YAAoB,EACpBC,QAAmB;IAEnB,OAAOA,SAASC,GAAG,CAAC,CAACC;QACnB,OAAO,IAAIb,QAAQ;YACjBQ,UAAUN,qBAAqBQ,cAAcG,QAAQL,QAAQ;YAC7DD,SAASM,QAAQN,OAAO;QAC1B;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASO,kBACdC,KAAa,EACbC,KAAsB;IAEtB,OAAOA,MAAML,QAAQ,CAACC,GAAG,CAAC,CAACC;QACzB,OAAO,IAAIb,QAAQ;YACjBQ,UAAUN,qBAAqB,CAAC,CAAC,EAAEa,MAAM,CAAC,CAAC,EAAEF,QAAQL,QAAQ;YAC7DD,SAASM,QAAQN,OAAO;QAC1B;IACF;AACF"}
|