@rtpaulino/entity 0.23.1 → 0.24.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 CHANGED
@@ -12,4 +12,5 @@ export * from './lib/primitive-deserializers.js';
12
12
  export * from './lib/validators.js';
13
13
  export * from './lib/zod-property.js';
14
14
  export * from './lib/injected-property.js';
15
+ export * from './lib/entity-definition.js';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -12,5 +12,6 @@ export * from './lib/primitive-deserializers.js';
12
12
  export * from './lib/validators.js';
13
13
  export * from './lib/zod-property.js';
14
14
  export * from './lib/injected-property.js';
15
+ export * from './lib/entity-definition.js';
15
16
 
16
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nexport * from './lib/entity.js';\nexport * from './lib/entity-utils.js';\nexport * from './lib/entity-di.js';\nexport * from './lib/entity-registry.js';\nexport * from './lib/types.js';\nexport * from './lib/property.js';\nexport * from './lib/validation-error.js';\nexport * from './lib/problem.js';\nexport * from './lib/validation-utils.js';\nexport * from './lib/primitive-deserializers.js';\nexport * from './lib/validators.js';\nexport * from './lib/zod-property.js';\nexport * from './lib/injected-property.js';\n"],"names":[],"mappings":"AAAA,OAAO,mBAAmB;AAE1B,cAAc,kBAAkB;AAChC,cAAc,wBAAwB;AACtC,cAAc,qBAAqB;AACnC,cAAc,2BAA2B;AACzC,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,mBAAmB;AACjC,cAAc,4BAA4B;AAC1C,cAAc,mCAAmC;AACjD,cAAc,sBAAsB;AACpC,cAAc,wBAAwB;AACtC,cAAc,6BAA6B"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import 'reflect-metadata';\n\nexport * from './lib/entity.js';\nexport * from './lib/entity-utils.js';\nexport * from './lib/entity-di.js';\nexport * from './lib/entity-registry.js';\nexport * from './lib/types.js';\nexport * from './lib/property.js';\nexport * from './lib/validation-error.js';\nexport * from './lib/problem.js';\nexport * from './lib/validation-utils.js';\nexport * from './lib/primitive-deserializers.js';\nexport * from './lib/validators.js';\nexport * from './lib/zod-property.js';\nexport * from './lib/injected-property.js';\nexport * from './lib/entity-definition.js';\n"],"names":[],"mappings":"AAAA,OAAO,mBAAmB;AAE1B,cAAc,kBAAkB;AAChC,cAAc,wBAAwB;AACtC,cAAc,qBAAqB;AACnC,cAAc,2BAA2B;AACzC,cAAc,iBAAiB;AAC/B,cAAc,oBAAoB;AAClC,cAAc,4BAA4B;AAC1C,cAAc,mBAAmB;AACjC,cAAc,4BAA4B;AAC1C,cAAc,mCAAmC;AACjD,cAAc,sBAAsB;AACpC,cAAc,wBAAwB;AACtC,cAAc,6BAA6B;AAC3C,cAAc,6BAA6B"}
@@ -0,0 +1,294 @@
1
+ import { PropertyOptions, type AnyCtor } from './types.js';
2
+ import { EntityOptions } from './entity.js';
3
+ import { Problem } from './problem.js';
4
+ import { stringPropertyOptions, enumPropertyOptions, numberPropertyOptions, intPropertyOptions, booleanPropertyOptions, datePropertyOptions, bigIntPropertyOptions, entityPropertyOptions, arrayPropertyOptions, passthroughPropertyOptions, discriminatedEntityPropertyOptions } from './property.js';
5
+ import { zodPropertyOptions } from './zod-property.js';
6
+ /**
7
+ * Configuration for defining an entity schema
8
+ */
9
+ export interface EntitySchemaConfig<T = any> {
10
+ /**
11
+ * Name for the entity (required for schema-based entities)
12
+ */
13
+ name: string;
14
+ /**
15
+ * Entity options (collection, stringifiable, etc.)
16
+ */
17
+ options?: Omit<EntityOptions, 'name'>;
18
+ /**
19
+ * Property definitions - key is property name, value is property options
20
+ */
21
+ properties: Record<string, PropertyOptions>;
22
+ /**
23
+ * Validator functions that will be attached to the entity class
24
+ * Each function receives the entity instance and returns problems
25
+ */
26
+ validators?: Array<(instance: T) => Problem[] | Promise<Problem[]>>;
27
+ /**
28
+ * Whether to register this entity in the EntityRegistry.
29
+ * For dynamic schemas, defaults to false to prevent memory leaks.
30
+ * Set to true if you need discriminated entity deserialization.
31
+ */
32
+ register?: boolean;
33
+ }
34
+ /**
35
+ * Wrapper object returned by EntitySchema.define() with EntityUtils methods
36
+ */
37
+ export interface EntitySchemaWrapper<T> {
38
+ /**
39
+ * The generated entity class
40
+ */
41
+ readonly entityClass: AnyCtor<T>;
42
+ /**
43
+ * Parse data into an entity instance
44
+ */
45
+ parse(data: unknown): Promise<T>;
46
+ /**
47
+ * Parse data into an entity instance without throwing
48
+ */
49
+ safeParse(data: unknown): Promise<{
50
+ success: true;
51
+ data: T;
52
+ problems: Problem[];
53
+ } | {
54
+ success: false;
55
+ data: undefined;
56
+ problems: Problem[];
57
+ }>;
58
+ /**
59
+ * Parse only present properties without throwing
60
+ */
61
+ parsePartial(data: unknown): Promise<Partial<T>>;
62
+ /**
63
+ * Parse only present properties without throwing
64
+ */
65
+ safeParsePartial(data: unknown): Promise<{
66
+ success: true;
67
+ data: Partial<T>;
68
+ problems: Problem[];
69
+ } | {
70
+ success: false;
71
+ data: undefined;
72
+ problems: Problem[];
73
+ }>;
74
+ /**
75
+ * Serialize entity instance to plain object
76
+ */
77
+ serialize(instance: T): unknown;
78
+ /**
79
+ * Update entity instance with new data
80
+ */
81
+ update(instance: T, data: unknown): Promise<T>;
82
+ /**
83
+ * Update entity instance with new data without throwing
84
+ */
85
+ safeUpdate(instance: T, data: unknown): Promise<{
86
+ success: true;
87
+ data: T;
88
+ problems: Problem[];
89
+ } | {
90
+ success: false;
91
+ data: T;
92
+ problems: Problem[];
93
+ }>;
94
+ /**
95
+ * Validate entity instance
96
+ */
97
+ validate(instance: T): Promise<Problem[]>;
98
+ /**
99
+ * Check if two instances are equal
100
+ */
101
+ equals(a: T, b: T): boolean;
102
+ /**
103
+ * Get differences between two instances
104
+ */
105
+ diff(a: T, b: T): Record<string, {
106
+ from: unknown;
107
+ to: unknown;
108
+ }>;
109
+ /**
110
+ * Get changed values as partial object
111
+ */
112
+ getChanges(a: T, b: T): Partial<T>;
113
+ }
114
+ /**
115
+ * Factory for creating schema-based entities without pre-defining a class
116
+ */
117
+ export declare class EntitySchema {
118
+ /**
119
+ * Define a new entity schema and return a wrapper with EntityUtils methods
120
+ *
121
+ * @param config - Schema configuration with name, properties, options, and validators
122
+ * @returns Wrapper object with parse, serialize, validate, etc. methods
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * const UserSchema = EntitySchema.define({
127
+ * name: 'User',
128
+ * properties: {
129
+ * name: { type: () => String },
130
+ * age: { type: () => Number, optional: true },
131
+ * tags: { type: () => String, array: true },
132
+ * },
133
+ * validators: [
134
+ * (user) => user.name.length < 2 ? [{ path: 'name', message: 'Too short' }] : []
135
+ * ]
136
+ * });
137
+ *
138
+ * const user = await UserSchema.parse({ name: 'John', age: 30, tags: ['admin'] });
139
+ * const serialized = UserSchema.serialize(user);
140
+ * const isValid = (await UserSchema.validate(user)).length === 0;
141
+ * ```
142
+ */
143
+ static define<T extends object = any>(config: EntitySchemaConfig<T>): EntitySchemaWrapper<T>;
144
+ }
145
+ /**
146
+ * Property definition helpers for EntitySchema
147
+ * These mirror the decorator-based property helpers but return PropertyOptions objects
148
+ */
149
+ export declare const EntityProps: {
150
+ /**
151
+ * String property with optional validation
152
+ * @example
153
+ * EntitySchema.define({
154
+ * name: 'User',
155
+ * properties: {
156
+ * name: EntityProps.String({ minLength: 2, maxLength: 50 }),
157
+ * email: EntityProps.String({ pattern: /^.+@.+\..+$/ }),
158
+ * }
159
+ * })
160
+ */
161
+ String: typeof stringPropertyOptions;
162
+ /**
163
+ * Enum property (validates string against enum values)
164
+ * @example
165
+ * enum Status { Active = 'active', Inactive = 'inactive' }
166
+ * EntitySchema.define({
167
+ * name: 'User',
168
+ * properties: {
169
+ * status: EntityProps.Enum(Status),
170
+ * }
171
+ * })
172
+ */
173
+ Enum: typeof enumPropertyOptions;
174
+ /**
175
+ * Number property with optional min/max validation
176
+ * @example
177
+ * EntitySchema.define({
178
+ * name: 'User',
179
+ * properties: {
180
+ * age: EntityProps.Number({ min: 0, max: 150 }),
181
+ * score: EntityProps.Number({ optional: true }),
182
+ * }
183
+ * })
184
+ */
185
+ Number: typeof numberPropertyOptions;
186
+ /**
187
+ * Integer property (number that must be an integer)
188
+ * @example
189
+ * EntitySchema.define({
190
+ * name: 'User',
191
+ * properties: {
192
+ * age: EntityProps.Int({ min: 0 }),
193
+ * }
194
+ * })
195
+ */
196
+ Int: typeof intPropertyOptions;
197
+ /**
198
+ * Boolean property
199
+ * @example
200
+ * EntitySchema.define({
201
+ * name: 'User',
202
+ * properties: {
203
+ * isActive: EntityProps.Boolean(),
204
+ * emailVerified: EntityProps.Boolean({ optional: true }),
205
+ * }
206
+ * })
207
+ */
208
+ Boolean: typeof booleanPropertyOptions;
209
+ /**
210
+ * Date property
211
+ * @example
212
+ * EntitySchema.define({
213
+ * name: 'Event',
214
+ * properties: {
215
+ * createdAt: EntityProps.Date(),
216
+ * scheduledFor: EntityProps.Date({ optional: true }),
217
+ * }
218
+ * })
219
+ */
220
+ Date: typeof datePropertyOptions;
221
+ /**
222
+ * BigInt property
223
+ * @example
224
+ * EntitySchema.define({
225
+ * name: 'Transaction',
226
+ * properties: {
227
+ * amount: EntityProps.BigInt(),
228
+ * }
229
+ * })
230
+ */
231
+ BigInt: typeof bigIntPropertyOptions;
232
+ /**
233
+ * Entity property (nested entity)
234
+ * @example
235
+ * const AddressSchema = EntitySchema.define({ ... });
236
+ * EntitySchema.define({
237
+ * name: 'User',
238
+ * properties: {
239
+ * address: EntityProps.Entity(() => AddressSchema.entityClass),
240
+ * }
241
+ * })
242
+ */
243
+ Entity: typeof entityPropertyOptions;
244
+ /**
245
+ * Array property
246
+ * @example
247
+ * EntitySchema.define({
248
+ * name: 'User',
249
+ * properties: {
250
+ * tags: EntityProps.Array(() => String),
251
+ * addresses: EntityProps.Array(() => AddressSchema.entityClass),
252
+ * }
253
+ * })
254
+ */
255
+ Array: typeof arrayPropertyOptions;
256
+ /**
257
+ * Passthrough property (no deserialization/validation)
258
+ * @example
259
+ * EntitySchema.define({
260
+ * name: 'Config',
261
+ * properties: {
262
+ * metadata: EntityProps.Passthrough(),
263
+ * }
264
+ * })
265
+ */
266
+ Passthrough: typeof passthroughPropertyOptions;
267
+ /**
268
+ * Zod schema property (validates using Zod schema)
269
+ * @example
270
+ * import { z } from 'zod';
271
+ * EntitySchema.define({
272
+ * name: 'User',
273
+ * properties: {
274
+ * data: EntityProps.Zod(z.object({
275
+ * name: z.string().min(3),
276
+ * age: z.number().int().min(0)
277
+ * })),
278
+ * }
279
+ * })
280
+ */
281
+ Zod: typeof zodPropertyOptions;
282
+ /**
283
+ * Discriminated entity property (for polymorphic entities with discriminator)
284
+ * @example
285
+ * EntitySchema.define({
286
+ * name: 'Shape',
287
+ * properties: {
288
+ * shape: EntityProps.DiscriminatedEntity({ discriminatorProperty: 'type' }),
289
+ * }
290
+ * })
291
+ */
292
+ DiscriminatedEntity: typeof discriminatedEntityPropertyOptions;
293
+ };
294
+ //# sourceMappingURL=entity-definition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-definition.d.ts","sourceRoot":"","sources":["../../src/lib/entity-definition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,273 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */ import { ENTITY_METADATA_KEY, ENTITY_OPTIONS_METADATA_KEY, ENTITY_VALIDATOR_METADATA_KEY, PROPERTY_METADATA_KEY, PROPERTY_OPTIONS_METADATA_KEY } from './types.js';
2
+ import { EntityRegistry } from './entity-registry.js';
3
+ import { EntityUtils } from './entity-utils.js';
4
+ import { stringPropertyOptions, enumPropertyOptions, numberPropertyOptions, intPropertyOptions, booleanPropertyOptions, datePropertyOptions, bigIntPropertyOptions, entityPropertyOptions, arrayPropertyOptions, passthroughPropertyOptions, discriminatedEntityPropertyOptions } from './property.js';
5
+ import { zodPropertyOptions } from './zod-property.js';
6
+ /**
7
+ * Define entity metadata on an existing class programmatically
8
+ * This sets the same metadata that @Entity() and @Property() decorators would set
9
+ *
10
+ * @param entityClass - The class to define as an entity
11
+ * @param config - Configuration with properties, options, and validators
12
+ * @internal
13
+ */ function defineEntity(entityClass, config) {
14
+ const entityName = config.name;
15
+ // 1. Mark as entity
16
+ Reflect.defineMetadata(ENTITY_METADATA_KEY, true, entityClass);
17
+ // 2. Set entity options with resolved name
18
+ const entityOptions = {
19
+ ...config.options,
20
+ name: entityName
21
+ };
22
+ Reflect.defineMetadata(ENTITY_OPTIONS_METADATA_KEY, entityOptions, entityClass);
23
+ // 3. Register in EntityRegistry if enabled
24
+ if (config.register) {
25
+ EntityRegistry.register(entityName, entityClass);
26
+ }
27
+ // 4. Set property keys
28
+ const propertyKeys = Object.keys(config.properties);
29
+ Reflect.defineMetadata(PROPERTY_METADATA_KEY, propertyKeys, entityClass.prototype);
30
+ // 5. Set property options
31
+ Reflect.defineMetadata(PROPERTY_OPTIONS_METADATA_KEY, config.properties, entityClass.prototype);
32
+ // 6. Set up validators if provided
33
+ if (config.validators && config.validators.length > 0) {
34
+ const validatorMethodNames = [];
35
+ config.validators.forEach((validatorFn, index)=>{
36
+ const methodName = `__dynamicValidator${index}`;
37
+ validatorMethodNames.push(methodName);
38
+ // Attach validator as instance method that uses 'this'
39
+ entityClass.prototype[methodName] = function() {
40
+ return validatorFn(this);
41
+ };
42
+ });
43
+ Reflect.defineMetadata(ENTITY_VALIDATOR_METADATA_KEY, validatorMethodNames, entityClass.prototype);
44
+ }
45
+ }
46
+ /**
47
+ * Factory for creating schema-based entities without pre-defining a class
48
+ */ export class EntitySchema {
49
+ /**
50
+ * Define a new entity schema and return a wrapper with EntityUtils methods
51
+ *
52
+ * @param config - Schema configuration with name, properties, options, and validators
53
+ * @returns Wrapper object with parse, serialize, validate, etc. methods
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const UserSchema = EntitySchema.define({
58
+ * name: 'User',
59
+ * properties: {
60
+ * name: { type: () => String },
61
+ * age: { type: () => Number, optional: true },
62
+ * tags: { type: () => String, array: true },
63
+ * },
64
+ * validators: [
65
+ * (user) => user.name.length < 2 ? [{ path: 'name', message: 'Too short' }] : []
66
+ * ]
67
+ * });
68
+ *
69
+ * const user = await UserSchema.parse({ name: 'John', age: 30, tags: ['admin'] });
70
+ * const serialized = UserSchema.serialize(user);
71
+ * const isValid = (await UserSchema.validate(user)).length === 0;
72
+ * ```
73
+ */ static define(config) {
74
+ // Generate anonymous entity class
75
+ const entityClass = class {
76
+ constructor(data){
77
+ Object.assign(this, data);
78
+ }
79
+ };
80
+ // Define entity metadata
81
+ defineEntity(entityClass, {
82
+ name: config.name,
83
+ options: config.options,
84
+ properties: config.properties,
85
+ validators: config.validators,
86
+ register: config.register ?? false
87
+ });
88
+ // Create wrapper with EntityUtils methods
89
+ const wrapper = {
90
+ entityClass,
91
+ async parse (data) {
92
+ return EntityUtils.parse(entityClass, data);
93
+ },
94
+ async safeParse (data) {
95
+ return EntityUtils.safeParse(entityClass, data);
96
+ },
97
+ async parsePartial (data) {
98
+ return EntityUtils.partialParse(entityClass, data);
99
+ },
100
+ async safeParsePartial (data) {
101
+ return EntityUtils.safePartialParse(entityClass, data);
102
+ },
103
+ serialize (instance) {
104
+ return EntityUtils.toJSON(instance);
105
+ },
106
+ async update (instance, data) {
107
+ return EntityUtils.update(instance, data);
108
+ },
109
+ async safeUpdate (instance, data) {
110
+ return EntityUtils.safeUpdate(instance, data);
111
+ },
112
+ async validate (instance) {
113
+ return EntityUtils.validate(instance);
114
+ },
115
+ equals (a, b) {
116
+ return EntityUtils.equals(a, b);
117
+ },
118
+ diff (a, b) {
119
+ const diffs = EntityUtils.diff(a, b);
120
+ const result = {};
121
+ for (const diff of diffs){
122
+ result[diff.property] = {
123
+ from: diff.oldValue,
124
+ to: diff.newValue
125
+ };
126
+ }
127
+ return result;
128
+ },
129
+ getChanges (a, b) {
130
+ return EntityUtils.changes(a, b);
131
+ }
132
+ };
133
+ return wrapper;
134
+ }
135
+ }
136
+ /**
137
+ * Property definition helpers for EntitySchema
138
+ * These mirror the decorator-based property helpers but return PropertyOptions objects
139
+ */ export const EntityProps = {
140
+ /**
141
+ * String property with optional validation
142
+ * @example
143
+ * EntitySchema.define({
144
+ * name: 'User',
145
+ * properties: {
146
+ * name: EntityProps.String({ minLength: 2, maxLength: 50 }),
147
+ * email: EntityProps.String({ pattern: /^.+@.+\..+$/ }),
148
+ * }
149
+ * })
150
+ */ String: stringPropertyOptions,
151
+ /**
152
+ * Enum property (validates string against enum values)
153
+ * @example
154
+ * enum Status { Active = 'active', Inactive = 'inactive' }
155
+ * EntitySchema.define({
156
+ * name: 'User',
157
+ * properties: {
158
+ * status: EntityProps.Enum(Status),
159
+ * }
160
+ * })
161
+ */ Enum: enumPropertyOptions,
162
+ /**
163
+ * Number property with optional min/max validation
164
+ * @example
165
+ * EntitySchema.define({
166
+ * name: 'User',
167
+ * properties: {
168
+ * age: EntityProps.Number({ min: 0, max: 150 }),
169
+ * score: EntityProps.Number({ optional: true }),
170
+ * }
171
+ * })
172
+ */ Number: numberPropertyOptions,
173
+ /**
174
+ * Integer property (number that must be an integer)
175
+ * @example
176
+ * EntitySchema.define({
177
+ * name: 'User',
178
+ * properties: {
179
+ * age: EntityProps.Int({ min: 0 }),
180
+ * }
181
+ * })
182
+ */ Int: intPropertyOptions,
183
+ /**
184
+ * Boolean property
185
+ * @example
186
+ * EntitySchema.define({
187
+ * name: 'User',
188
+ * properties: {
189
+ * isActive: EntityProps.Boolean(),
190
+ * emailVerified: EntityProps.Boolean({ optional: true }),
191
+ * }
192
+ * })
193
+ */ Boolean: booleanPropertyOptions,
194
+ /**
195
+ * Date property
196
+ * @example
197
+ * EntitySchema.define({
198
+ * name: 'Event',
199
+ * properties: {
200
+ * createdAt: EntityProps.Date(),
201
+ * scheduledFor: EntityProps.Date({ optional: true }),
202
+ * }
203
+ * })
204
+ */ Date: datePropertyOptions,
205
+ /**
206
+ * BigInt property
207
+ * @example
208
+ * EntitySchema.define({
209
+ * name: 'Transaction',
210
+ * properties: {
211
+ * amount: EntityProps.BigInt(),
212
+ * }
213
+ * })
214
+ */ BigInt: bigIntPropertyOptions,
215
+ /**
216
+ * Entity property (nested entity)
217
+ * @example
218
+ * const AddressSchema = EntitySchema.define({ ... });
219
+ * EntitySchema.define({
220
+ * name: 'User',
221
+ * properties: {
222
+ * address: EntityProps.Entity(() => AddressSchema.entityClass),
223
+ * }
224
+ * })
225
+ */ Entity: entityPropertyOptions,
226
+ /**
227
+ * Array property
228
+ * @example
229
+ * EntitySchema.define({
230
+ * name: 'User',
231
+ * properties: {
232
+ * tags: EntityProps.Array(() => String),
233
+ * addresses: EntityProps.Array(() => AddressSchema.entityClass),
234
+ * }
235
+ * })
236
+ */ Array: arrayPropertyOptions,
237
+ /**
238
+ * Passthrough property (no deserialization/validation)
239
+ * @example
240
+ * EntitySchema.define({
241
+ * name: 'Config',
242
+ * properties: {
243
+ * metadata: EntityProps.Passthrough(),
244
+ * }
245
+ * })
246
+ */ Passthrough: passthroughPropertyOptions,
247
+ /**
248
+ * Zod schema property (validates using Zod schema)
249
+ * @example
250
+ * import { z } from 'zod';
251
+ * EntitySchema.define({
252
+ * name: 'User',
253
+ * properties: {
254
+ * data: EntityProps.Zod(z.object({
255
+ * name: z.string().min(3),
256
+ * age: z.number().int().min(0)
257
+ * })),
258
+ * }
259
+ * })
260
+ */ Zod: zodPropertyOptions,
261
+ /**
262
+ * Discriminated entity property (for polymorphic entities with discriminator)
263
+ * @example
264
+ * EntitySchema.define({
265
+ * name: 'Shape',
266
+ * properties: {
267
+ * shape: EntityProps.DiscriminatedEntity({ discriminatorProperty: 'type' }),
268
+ * }
269
+ * })
270
+ */ DiscriminatedEntity: discriminatedEntityPropertyOptions
271
+ };
272
+
273
+ //# sourceMappingURL=entity-definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/entity-definition.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n ENTITY_METADATA_KEY,\n ENTITY_OPTIONS_METADATA_KEY,\n ENTITY_VALIDATOR_METADATA_KEY,\n PROPERTY_METADATA_KEY,\n PROPERTY_OPTIONS_METADATA_KEY,\n PropertyOptions,\n type AnyCtor,\n} from './types.js';\nimport { EntityOptions } from './entity.js';\nimport { EntityRegistry } from './entity-registry.js';\nimport { EntityUtils } from './entity-utils.js';\nimport { Problem } from './problem.js';\nimport {\n stringPropertyOptions,\n enumPropertyOptions,\n numberPropertyOptions,\n intPropertyOptions,\n booleanPropertyOptions,\n datePropertyOptions,\n bigIntPropertyOptions,\n entityPropertyOptions,\n arrayPropertyOptions,\n passthroughPropertyOptions,\n discriminatedEntityPropertyOptions,\n} from './property.js';\nimport { zodPropertyOptions } from './zod-property.js';\n\n/**\n * Configuration for defining an entity schema\n */\nexport interface EntitySchemaConfig<T = any> {\n /**\n * Name for the entity (required for schema-based entities)\n */\n name: string;\n /**\n * Entity options (collection, stringifiable, etc.)\n */\n options?: Omit<EntityOptions, 'name'>;\n /**\n * Property definitions - key is property name, value is property options\n */\n properties: Record<string, PropertyOptions>;\n /**\n * Validator functions that will be attached to the entity class\n * Each function receives the entity instance and returns problems\n */\n validators?: Array<(instance: T) => Problem[] | Promise<Problem[]>>;\n /**\n * Whether to register this entity in the EntityRegistry.\n * For dynamic schemas, defaults to false to prevent memory leaks.\n * Set to true if you need discriminated entity deserialization.\n */\n register?: boolean;\n}\n\n/**\n * Wrapper object returned by EntitySchema.define() with EntityUtils methods\n */\nexport interface EntitySchemaWrapper<T> {\n /**\n * The generated entity class\n */\n readonly entityClass: AnyCtor<T>;\n\n /**\n * Parse data into an entity instance\n */\n parse(data: unknown): Promise<T>;\n\n /**\n * Parse data into an entity instance without throwing\n */\n safeParse(\n data: unknown,\n ): Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n >;\n\n /**\n * Parse only present properties without throwing\n */\n parsePartial(data: unknown): Promise<Partial<T>>;\n\n /**\n * Parse only present properties without throwing\n */\n safeParsePartial(\n data: unknown,\n ): Promise<\n | { success: true; data: Partial<T>; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n >;\n\n /**\n * Serialize entity instance to plain object\n */\n serialize(instance: T): unknown;\n\n /**\n * Update entity instance with new data\n */\n update(instance: T, data: unknown): Promise<T>;\n\n /**\n * Update entity instance with new data without throwing\n */\n safeUpdate(\n instance: T,\n data: unknown,\n ): Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: T; problems: Problem[] }\n >;\n\n /**\n * Validate entity instance\n */\n validate(instance: T): Promise<Problem[]>;\n\n /**\n * Check if two instances are equal\n */\n equals(a: T, b: T): boolean;\n\n /**\n * Get differences between two instances\n */\n diff(a: T, b: T): Record<string, { from: unknown; to: unknown }>;\n\n /**\n * Get changed values as partial object\n */\n getChanges(a: T, b: T): Partial<T>;\n}\n\n/**\n * Define entity metadata on an existing class programmatically\n * This sets the same metadata that @Entity() and @Property() decorators would set\n *\n * @param entityClass - The class to define as an entity\n * @param config - Configuration with properties, options, and validators\n * @internal\n */\nfunction defineEntity<T>(\n entityClass: AnyCtor<T>,\n config: EntitySchemaConfig<T>,\n): void {\n const entityName = config.name;\n\n // 1. Mark as entity\n Reflect.defineMetadata(ENTITY_METADATA_KEY, true, entityClass);\n\n // 2. Set entity options with resolved name\n const entityOptions: EntityOptions = {\n ...config.options,\n name: entityName,\n };\n Reflect.defineMetadata(\n ENTITY_OPTIONS_METADATA_KEY,\n entityOptions,\n entityClass,\n );\n\n // 3. Register in EntityRegistry if enabled\n if (config.register) {\n EntityRegistry.register(entityName, entityClass);\n }\n\n // 4. Set property keys\n const propertyKeys = Object.keys(config.properties);\n Reflect.defineMetadata(\n PROPERTY_METADATA_KEY,\n propertyKeys,\n entityClass.prototype,\n );\n\n // 5. Set property options\n Reflect.defineMetadata(\n PROPERTY_OPTIONS_METADATA_KEY,\n config.properties,\n entityClass.prototype,\n );\n\n // 6. Set up validators if provided\n if (config.validators && config.validators.length > 0) {\n const validatorMethodNames: string[] = [];\n\n config.validators.forEach((validatorFn, index) => {\n const methodName = `__dynamicValidator${index}`;\n validatorMethodNames.push(methodName);\n\n // Attach validator as instance method that uses 'this'\n (entityClass.prototype as any)[methodName] = function ():\n | Problem[]\n | Promise<Problem[]> {\n return validatorFn(this);\n };\n });\n\n Reflect.defineMetadata(\n ENTITY_VALIDATOR_METADATA_KEY,\n validatorMethodNames,\n entityClass.prototype,\n );\n }\n}\n\n/**\n * Factory for creating schema-based entities without pre-defining a class\n */\nexport class EntitySchema {\n /**\n * Define a new entity schema and return a wrapper with EntityUtils methods\n *\n * @param config - Schema configuration with name, properties, options, and validators\n * @returns Wrapper object with parse, serialize, validate, etc. methods\n *\n * @example\n * ```typescript\n * const UserSchema = EntitySchema.define({\n * name: 'User',\n * properties: {\n * name: { type: () => String },\n * age: { type: () => Number, optional: true },\n * tags: { type: () => String, array: true },\n * },\n * validators: [\n * (user) => user.name.length < 2 ? [{ path: 'name', message: 'Too short' }] : []\n * ]\n * });\n *\n * const user = await UserSchema.parse({ name: 'John', age: 30, tags: ['admin'] });\n * const serialized = UserSchema.serialize(user);\n * const isValid = (await UserSchema.validate(user)).length === 0;\n * ```\n */\n static define<T extends object = any>(\n config: EntitySchemaConfig<T>,\n ): EntitySchemaWrapper<T> {\n // Generate anonymous entity class\n const entityClass = class {\n constructor(data: any) {\n Object.assign(this, data);\n }\n } as unknown as AnyCtor<T>;\n\n // Define entity metadata\n defineEntity(entityClass, {\n name: config.name,\n options: config.options,\n properties: config.properties,\n validators: config.validators,\n register: config.register ?? false, // Default to false for dynamic schemas to prevent memory leaks\n });\n\n // Create wrapper with EntityUtils methods\n const wrapper: EntitySchemaWrapper<T> = {\n entityClass,\n\n async parse(data: unknown): Promise<T> {\n return EntityUtils.parse(entityClass as any, data) as Promise<T>;\n },\n\n async safeParse(data: unknown) {\n return EntityUtils.safeParse(entityClass as any, data) as Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n >;\n },\n\n async parsePartial(data: unknown): Promise<Partial<T>> {\n return EntityUtils.partialParse(entityClass as any, data) as Promise<\n Partial<T>\n >;\n },\n\n async safeParsePartial(data: unknown) {\n return EntityUtils.safePartialParse(\n entityClass as any,\n data,\n ) as unknown as Promise<\n | { success: true; data: Partial<T>; problems: Problem[] }\n | { success: false; data: undefined; problems: Problem[] }\n >;\n },\n\n serialize(instance: T): unknown {\n return EntityUtils.toJSON(instance as any);\n },\n\n async update(instance: T, data: unknown): Promise<T> {\n return EntityUtils.update(instance as any, data as any) as Promise<T>;\n },\n\n async safeUpdate(instance: T, data: unknown) {\n return EntityUtils.safeUpdate(instance as any, data as any) as Promise<\n | { success: true; data: T; problems: Problem[] }\n | { success: false; data: T; problems: Problem[] }\n >;\n },\n\n async validate(instance: T): Promise<Problem[]> {\n return EntityUtils.validate(instance as any);\n },\n\n equals(a: T, b: T): boolean {\n return EntityUtils.equals(a as any, b as any);\n },\n\n diff(a: T, b: T): Record<string, { from: unknown; to: unknown }> {\n const diffs = EntityUtils.diff(a as any, b as any);\n const result: Record<string, { from: unknown; to: unknown }> = {};\n for (const diff of diffs) {\n result[diff.property] = { from: diff.oldValue, to: diff.newValue };\n }\n return result;\n },\n\n getChanges(a: T, b: T): Partial<T> {\n return EntityUtils.changes(a as any, b as any) as Partial<T>;\n },\n };\n\n return wrapper;\n }\n}\n\n/**\n * Property definition helpers for EntitySchema\n * These mirror the decorator-based property helpers but return PropertyOptions objects\n */\nexport const EntityProps = {\n /**\n * String property with optional validation\n * @example\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * name: EntityProps.String({ minLength: 2, maxLength: 50 }),\n * email: EntityProps.String({ pattern: /^.+@.+\\..+$/ }),\n * }\n * })\n */\n String: stringPropertyOptions,\n\n /**\n * Enum property (validates string against enum values)\n * @example\n * enum Status { Active = 'active', Inactive = 'inactive' }\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * status: EntityProps.Enum(Status),\n * }\n * })\n */\n Enum: enumPropertyOptions,\n\n /**\n * Number property with optional min/max validation\n * @example\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * age: EntityProps.Number({ min: 0, max: 150 }),\n * score: EntityProps.Number({ optional: true }),\n * }\n * })\n */\n Number: numberPropertyOptions,\n\n /**\n * Integer property (number that must be an integer)\n * @example\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * age: EntityProps.Int({ min: 0 }),\n * }\n * })\n */\n Int: intPropertyOptions,\n\n /**\n * Boolean property\n * @example\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * isActive: EntityProps.Boolean(),\n * emailVerified: EntityProps.Boolean({ optional: true }),\n * }\n * })\n */\n Boolean: booleanPropertyOptions,\n\n /**\n * Date property\n * @example\n * EntitySchema.define({\n * name: 'Event',\n * properties: {\n * createdAt: EntityProps.Date(),\n * scheduledFor: EntityProps.Date({ optional: true }),\n * }\n * })\n */\n Date: datePropertyOptions,\n\n /**\n * BigInt property\n * @example\n * EntitySchema.define({\n * name: 'Transaction',\n * properties: {\n * amount: EntityProps.BigInt(),\n * }\n * })\n */\n BigInt: bigIntPropertyOptions,\n\n /**\n * Entity property (nested entity)\n * @example\n * const AddressSchema = EntitySchema.define({ ... });\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * address: EntityProps.Entity(() => AddressSchema.entityClass),\n * }\n * })\n */\n Entity: entityPropertyOptions,\n\n /**\n * Array property\n * @example\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * tags: EntityProps.Array(() => String),\n * addresses: EntityProps.Array(() => AddressSchema.entityClass),\n * }\n * })\n */\n Array: arrayPropertyOptions,\n\n /**\n * Passthrough property (no deserialization/validation)\n * @example\n * EntitySchema.define({\n * name: 'Config',\n * properties: {\n * metadata: EntityProps.Passthrough(),\n * }\n * })\n */\n Passthrough: passthroughPropertyOptions,\n\n /**\n * Zod schema property (validates using Zod schema)\n * @example\n * import { z } from 'zod';\n * EntitySchema.define({\n * name: 'User',\n * properties: {\n * data: EntityProps.Zod(z.object({\n * name: z.string().min(3),\n * age: z.number().int().min(0)\n * })),\n * }\n * })\n */\n Zod: zodPropertyOptions,\n\n /**\n * Discriminated entity property (for polymorphic entities with discriminator)\n * @example\n * EntitySchema.define({\n * name: 'Shape',\n * properties: {\n * shape: EntityProps.DiscriminatedEntity({ discriminatorProperty: 'type' }),\n * }\n * })\n */\n DiscriminatedEntity: discriminatedEntityPropertyOptions,\n};\n"],"names":["ENTITY_METADATA_KEY","ENTITY_OPTIONS_METADATA_KEY","ENTITY_VALIDATOR_METADATA_KEY","PROPERTY_METADATA_KEY","PROPERTY_OPTIONS_METADATA_KEY","EntityRegistry","EntityUtils","stringPropertyOptions","enumPropertyOptions","numberPropertyOptions","intPropertyOptions","booleanPropertyOptions","datePropertyOptions","bigIntPropertyOptions","entityPropertyOptions","arrayPropertyOptions","passthroughPropertyOptions","discriminatedEntityPropertyOptions","zodPropertyOptions","defineEntity","entityClass","config","entityName","name","Reflect","defineMetadata","entityOptions","options","register","propertyKeys","Object","keys","properties","prototype","validators","length","validatorMethodNames","forEach","validatorFn","index","methodName","push","EntitySchema","define","data","assign","wrapper","parse","safeParse","parsePartial","partialParse","safeParsePartial","safePartialParse","serialize","instance","toJSON","update","safeUpdate","validate","equals","a","b","diff","diffs","result","property","from","oldValue","to","newValue","getChanges","changes","EntityProps","String","Enum","Number","Int","Boolean","Date","BigInt","Entity","Array","Passthrough","Zod","DiscriminatedEntity"],"mappings":"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"}
@@ -28,6 +28,12 @@ export interface EntityOptions {
28
28
  * Used by @CollectionEntity ('collection') and @Stringifiable ('value').
29
29
  */
30
30
  wrapperProperty?: string;
31
+ /**
32
+ * Whether to register this entity in the EntityRegistry.
33
+ * Set to false for dynamic entities to prevent memory leaks.
34
+ * Defaults to true.
35
+ */
36
+ register?: boolean;
31
37
  }
32
38
  /**
33
39
  * Decorator that marks a class as an Entity.
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/lib/entity.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,cAAc,CAqBlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAMhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAmBjD"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../src/lib/entity.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,cAAc,CAwBlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAMhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,aAAa,CAC3B,OAAO,GAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAM,GACxC,cAAc,CAEhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAmBjD"}