@woltz/rich-domain 1.2.0 → 1.2.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/aggregate-changes.d.ts +164 -0
  3. package/dist/aggregate-changes.d.ts.map +1 -0
  4. package/dist/aggregate-changes.js +281 -0
  5. package/dist/aggregate-changes.js.map +1 -0
  6. package/dist/base-entity.d.ts +32 -8
  7. package/dist/base-entity.d.ts.map +1 -1
  8. package/dist/base-entity.js +117 -86
  9. package/dist/base-entity.js.map +1 -1
  10. package/dist/criteria.d.ts +3 -3
  11. package/dist/criteria.d.ts.map +1 -1
  12. package/dist/criteria.js.map +1 -1
  13. package/dist/crypto.d.ts +3 -0
  14. package/dist/crypto.d.ts.map +1 -0
  15. package/dist/crypto.js +29 -0
  16. package/dist/crypto.js.map +1 -0
  17. package/dist/entity-changes.d.ts +84 -0
  18. package/dist/entity-changes.d.ts.map +1 -0
  19. package/dist/entity-changes.js +135 -0
  20. package/dist/entity-changes.js.map +1 -0
  21. package/dist/entity-schema-registry.d.ts +148 -0
  22. package/dist/entity-schema-registry.d.ts.map +1 -0
  23. package/dist/entity-schema-registry.js +219 -0
  24. package/dist/entity-schema-registry.js.map +1 -0
  25. package/dist/history-tracker.d.ts +97 -0
  26. package/dist/history-tracker.d.ts.map +1 -0
  27. package/dist/history-tracker.js +805 -0
  28. package/dist/history-tracker.js.map +1 -0
  29. package/dist/id.d.ts +11 -10
  30. package/dist/id.d.ts.map +1 -1
  31. package/dist/id.js +4 -28
  32. package/dist/id.js.map +1 -1
  33. package/dist/index.d.ts +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/mapper.d.ts +1 -1
  38. package/dist/mapper.d.ts.map +1 -1
  39. package/dist/mapper.js.map +1 -1
  40. package/dist/repository/base-repository.d.ts +6 -32
  41. package/dist/repository/base-repository.d.ts.map +1 -1
  42. package/dist/repository/base-repository.js +0 -27
  43. package/dist/repository/base-repository.js.map +1 -1
  44. package/dist/repository/unit-of-work.d.ts +0 -25
  45. package/dist/repository/unit-of-work.d.ts.map +1 -1
  46. package/dist/repository/unit-of-work.js +0 -25
  47. package/dist/repository/unit-of-work.js.map +1 -1
  48. package/dist/types/change-tracker.d.ts +186 -0
  49. package/dist/types/change-tracker.d.ts.map +1 -0
  50. package/dist/types/change-tracker.js +2 -0
  51. package/dist/types/change-tracker.js.map +1 -0
  52. package/dist/types/criteria.d.ts +5 -1
  53. package/dist/types/criteria.d.ts.map +1 -1
  54. package/dist/types/history-tracker.d.ts +11 -0
  55. package/dist/types/history-tracker.d.ts.map +1 -1
  56. package/dist/types/utils.d.ts +0 -1
  57. package/dist/types/utils.d.ts.map +1 -1
  58. package/dist/validation-error.d.ts.map +1 -1
  59. package/dist/validation-error.js +0 -3
  60. package/dist/validation-error.js.map +1 -1
  61. package/dist/value-object.d.ts +57 -8
  62. package/dist/value-object.d.ts.map +1 -1
  63. package/dist/value-object.js +49 -21
  64. package/dist/value-object.js.map +1 -1
  65. package/package.json +2 -1
  66. package/src/aggregate-changes.ts +335 -0
  67. package/src/base-entity.ts +140 -100
  68. package/src/criteria.ts +2 -1
  69. package/src/crypto.ts +31 -0
  70. package/src/entity-changes.ts +151 -0
  71. package/src/entity-schema-registry.ts +275 -0
  72. package/src/history-tracker.ts +1114 -0
  73. package/src/id.ts +17 -26
  74. package/src/index.ts +1 -0
  75. package/src/mapper.ts +4 -1
  76. package/src/repository/base-repository.ts +6 -37
  77. package/src/repository/unit-of-work.ts +0 -25
  78. package/src/types/change-tracker.ts +221 -0
  79. package/src/types/criteria.ts +6 -1
  80. package/src/types/history-tracker.ts +13 -0
  81. package/src/types/utils.ts +0 -9
  82. package/src/validation-error.ts +0 -4
  83. package/src/value-object.ts +84 -23
  84. package/tests/aggregate-changes.test.ts +284 -0
  85. package/tests/criteria.test.ts +122 -161
  86. package/tests/entity-equality.test.ts +38 -61
  87. package/tests/entity-schema-registry.test.ts +382 -0
  88. package/tests/entity-validation.test.ts +7 -94
  89. package/tests/history-tracker.spec.ts +349 -617
  90. package/tests/id.test.ts +41 -44
  91. package/tests/load-test/data.json +346041 -0
  92. package/tests/load-test/entities.ts +97 -0
  93. package/tests/load-test/generate-data.ts +81 -0
  94. package/tests/load-test/lead-to-domain.mapper.ts +24 -0
  95. package/tests/load-test/load.test.ts +38 -0
  96. package/tests/repository.test.ts +30 -54
  97. package/tests/to-json.test.ts +14 -18
  98. package/tests/utils.ts +138 -102
  99. package/tests/value-objects.test.ts +57 -29
  100. package/dist/deep-proxy.d.ts +0 -36
  101. package/dist/deep-proxy.d.ts.map +0 -1
  102. package/dist/deep-proxy.js +0 -384
  103. package/dist/deep-proxy.js.map +0 -1
  104. package/src/deep-proxy.ts +0 -447
  105. package/tests/entity.test.ts +0 -33
@@ -0,0 +1,135 @@
1
+ // ============================================================================
2
+ // Entity Changes
3
+ // Changes filtered by entity type
4
+ // ============================================================================
5
+ /**
6
+ * Represents the changes filtered for a specific entity.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const changes = user.getChanges();
11
+ * const postChanges = changes.for('Post');
12
+ *
13
+ * if (postChanges.hasCreates()) {
14
+ * console.log('Created posts:', postChanges.creates);
15
+ * }
16
+ *
17
+ * if (postChanges.hasUpdates()) {
18
+ * postChanges.updates.forEach(({ entity, changed }) => {
19
+ * console.log(`Post ${entity.id} has changed:`, changed);
20
+ * });
21
+ * }
22
+ * ```
23
+ */
24
+ export class EntityChanges {
25
+ constructor(operations) {
26
+ this.operations = operations;
27
+ }
28
+ /**
29
+ * Returns all created entities
30
+ */
31
+ get creates() {
32
+ return this.operations
33
+ .filter((op) => op.type === "create")
34
+ .map((op) => op.data);
35
+ }
36
+ /**
37
+ * Returns all updated entities with their changed fields
38
+ */
39
+ get updates() {
40
+ return this.operations
41
+ .filter((op) => op.type === "update")
42
+ .map((op) => ({
43
+ entity: op.data,
44
+ changed: op.changedFields,
45
+ }));
46
+ }
47
+ /**
48
+ * Returns all deleted entities
49
+ */
50
+ get deletes() {
51
+ return this.operations
52
+ .filter((op) => op.type === "delete")
53
+ .map((op) => op.data);
54
+ }
55
+ /**
56
+ * Returns the IDs of the created entities
57
+ */
58
+ get createIds() {
59
+ return this.operations
60
+ .filter((op) => op.type === "create")
61
+ .map((op) => this.extractId(op.data))
62
+ .filter((id) => id !== undefined);
63
+ }
64
+ /**
65
+ * Returns the IDs of the updated entities
66
+ */
67
+ get updateIds() {
68
+ return this.operations
69
+ .filter((op) => op.type === "update")
70
+ .map((op) => op.id);
71
+ }
72
+ /**
73
+ * Returns the IDs of the deleted entities
74
+ */
75
+ get deleteIds() {
76
+ return this.operations
77
+ .filter((op) => op.type === "delete")
78
+ .map((op) => op.id);
79
+ }
80
+ /**
81
+ * Checks if there are any creates
82
+ */
83
+ hasCreates() {
84
+ return this.creates.length > 0;
85
+ }
86
+ /**
87
+ * Checks if there are any updates
88
+ */
89
+ hasUpdates() {
90
+ return this.updates.length > 0;
91
+ }
92
+ /**
93
+ * Checks if there are any deletes
94
+ */
95
+ hasDeletes() {
96
+ return this.deletes.length > 0;
97
+ }
98
+ /**
99
+ * Checks if there is any change
100
+ */
101
+ hasChanges() {
102
+ return this.operations.length > 0;
103
+ }
104
+ /**
105
+ * Checks if it is empty (no changes)
106
+ */
107
+ isEmpty() {
108
+ return this.operations.length === 0;
109
+ }
110
+ /**
111
+ * Returns the total number of operations
112
+ */
113
+ get count() {
114
+ return this.operations.length;
115
+ }
116
+ /**
117
+ * Returns the raw operations (for advanced use cases)
118
+ */
119
+ get rawOperations() {
120
+ return [...this.operations];
121
+ }
122
+ /**
123
+ * Extracts the ID from an entity
124
+ */
125
+ extractId(entity) {
126
+ if (!entity)
127
+ return undefined;
128
+ if (entity.id?.value)
129
+ return entity.id.value;
130
+ if (typeof entity.id === "string")
131
+ return entity.id;
132
+ return undefined;
133
+ }
134
+ }
135
+ //# sourceMappingURL=entity-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-changes.js","sourceRoot":"","sources":["../src/entity-changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ import { Entity } from "./entity";
2
+ import { ValueObject } from "./value-object";
3
+ /**
4
+ * Mapping schema for a domain entity.
5
+ */
6
+ export interface EntitySchema {
7
+ /** Entity name in the domain (e.g., 'User', 'Post') */
8
+ entity: string;
9
+ /** Table name in the database (e.g., 'users', 'blog_posts') */
10
+ table: string;
11
+ /**
12
+ * Field mapping: domain → database.
13
+ * Only include fields with different names.
14
+ * @example { email: 'user_email', createdAt: 'created_at' }
15
+ */
16
+ fields?: Record<string, string>;
17
+ /**
18
+ * FK configuration for parent relation.
19
+ */
20
+ parentFk?: {
21
+ /** Name of the FK field in the database (e.g., 'author_id') */
22
+ field: string;
23
+ /** Name of the parent entity (e.g., 'User') */
24
+ parentEntity: string;
25
+ };
26
+ }
27
+ /**
28
+ * Result of entity mapping.
29
+ */
30
+ export interface MappedEntityData {
31
+ [key: string]: any;
32
+ }
33
+ /**
34
+ * Registry for mapping domain entities to database tables and fields.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const registry = new EntitySchemaRegistry()
39
+ * .register({
40
+ * entity: 'User',
41
+ * table: 'users',
42
+ * fields: { email: 'user_email', name: 'user_name' },
43
+ * })
44
+ * .register({
45
+ * entity: 'Post',
46
+ * table: 'blog_posts',
47
+ * fields: { content: 'post_content' },
48
+ * parentFk: { field: 'author_id', parentEntity: 'User' },
49
+ * });
50
+ *
51
+ * const table = registry.getTable('Post'); // 'blog_posts'
52
+ * const mapped = registry.mapFields('User', { email: 'test@test.com' });
53
+ * // { user_email: 'test@test.com' }
54
+ * ```
55
+ */
56
+ export declare class EntitySchemaRegistry {
57
+ private schemas;
58
+ /**
59
+ * Registers an entity schema.
60
+ * @param schema - Schema to be registered.
61
+ * @returns this (for chaining)
62
+ */
63
+ register(schema: EntitySchema): this;
64
+ /**
65
+ * Registers multiple schemas at once.
66
+ * @param schemas - Array of schemas.
67
+ * @returns this (for chaining)
68
+ */
69
+ registerAll(schemas: EntitySchema[]): this;
70
+ /**
71
+ * Gets the schema of an entity.
72
+ * @param entity - Entity name.
73
+ * @throws Error if the entity is not registered.
74
+ */
75
+ getSchema(entity: string): EntitySchema;
76
+ /**
77
+ * Checks if an entity is registered.
78
+ * @param entity - Entity name.
79
+ */
80
+ has(entity: string): boolean;
81
+ /**
82
+ * Gets the table name for an entity.
83
+ * @param entity - Entity name.
84
+ */
85
+ getTable(entity: string): string;
86
+ /**
87
+ * Gets the field mapping for an entity.
88
+ * @param entity - Entity name.
89
+ */
90
+ getFieldsMap(entity: string): Record<string, string>;
91
+ /**
92
+ * Maps a domain field name to the database field name.
93
+ * @param entity - Entity name.
94
+ * @param fieldName - Domain field name.
95
+ */
96
+ mapFieldName(entity: string, fieldName: string): string;
97
+ /**
98
+ * Maps fields of a domain object to database field names.
99
+ * Ignores values that are Entity, ValueObject, or Arrays.
100
+ *
101
+ * @param entity - Entity name.
102
+ * @param data - Data to be mapped.
103
+ */
104
+ mapFields(entity: string, data: Record<string, any>): MappedEntityData;
105
+ /**
106
+ * Maps a complete domain entity to database data.
107
+ * Used for CREATE operations.
108
+ *
109
+ * @param entity - Entity name.
110
+ * @param domainEntity - Domain entity instance.
111
+ */
112
+ mapEntity(entity: string, domainEntity: Entity<any> | ValueObject<any>): MappedEntityData;
113
+ /**
114
+ * Gets the FK object to relate with the parent.
115
+ *
116
+ * @param entity - Entity name.
117
+ * @param parentId - Parent ID.
118
+ * @returns Object with the FK field or null if there is no parent.
119
+ */
120
+ getParentFk(entity: string, parentId: string): Record<string, string> | null;
121
+ /**
122
+ * Gets the name of the parent entity.
123
+ * @param entity - Entity name.
124
+ */
125
+ getParentEntity(entity: string): string | null;
126
+ /**
127
+ * Gets the FK field name.
128
+ * @param entity - Entity name.
129
+ */
130
+ getParentFkField(entity: string): string | null;
131
+ /**
132
+ * Lists all registered entities.
133
+ */
134
+ getRegisteredEntities(): string[];
135
+ /**
136
+ * Clears all registered schemas.
137
+ */
138
+ clear(): void;
139
+ /**
140
+ * Checks if a value is Entity, ValueObject, or Array.
141
+ */
142
+ private isEntityOrCollection;
143
+ /**
144
+ * Normalizes a value for persistence.
145
+ */
146
+ private normalizeValue;
147
+ }
148
+ //# sourceMappingURL=entity-schema-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-schema-registry.d.ts","sourceRoot":"","sources":["../src/entity-schema-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IAEf,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,CAAC,EAAE;QACT,+DAA+D;QAC/D,KAAK,EAAE,MAAM,CAAC;QACd,+CAA+C;QAC/C,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,OAAO,CAAmC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAUpC;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IAK1C;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY;IAWvC;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI5B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAIpD;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAKvD;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,gBAAgB;IAetE;;;;;;OAMG;IACH,SAAS,CACP,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAC3C,gBAAgB;IA0BnB;;;;;;OAMG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAO5E;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK9C;;;OAGG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK/C;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAIjC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAc5B;;OAEG;IACH,OAAO,CAAC,cAAc;CAUvB"}
@@ -0,0 +1,219 @@
1
+ import { Entity } from "./entity";
2
+ import { ValueObject } from "./value-object";
3
+ import { Id } from "./id";
4
+ /**
5
+ * Registry for mapping domain entities to database tables and fields.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const registry = new EntitySchemaRegistry()
10
+ * .register({
11
+ * entity: 'User',
12
+ * table: 'users',
13
+ * fields: { email: 'user_email', name: 'user_name' },
14
+ * })
15
+ * .register({
16
+ * entity: 'Post',
17
+ * table: 'blog_posts',
18
+ * fields: { content: 'post_content' },
19
+ * parentFk: { field: 'author_id', parentEntity: 'User' },
20
+ * });
21
+ *
22
+ * const table = registry.getTable('Post'); // 'blog_posts'
23
+ * const mapped = registry.mapFields('User', { email: 'test@test.com' });
24
+ * // { user_email: 'test@test.com' }
25
+ * ```
26
+ */
27
+ export class EntitySchemaRegistry {
28
+ constructor() {
29
+ this.schemas = new Map();
30
+ }
31
+ /**
32
+ * Registers an entity schema.
33
+ * @param schema - Schema to be registered.
34
+ * @returns this (for chaining)
35
+ */
36
+ register(schema) {
37
+ if (this.schemas.has(schema.entity)) {
38
+ console.warn(`EntitySchemaRegistry: Schema for '${schema.entity}' is being overwritten`);
39
+ }
40
+ this.schemas.set(schema.entity, schema);
41
+ return this;
42
+ }
43
+ /**
44
+ * Registers multiple schemas at once.
45
+ * @param schemas - Array of schemas.
46
+ * @returns this (for chaining)
47
+ */
48
+ registerAll(schemas) {
49
+ schemas.forEach((schema) => this.register(schema));
50
+ return this;
51
+ }
52
+ /**
53
+ * Gets the schema of an entity.
54
+ * @param entity - Entity name.
55
+ * @throws Error if the entity is not registered.
56
+ */
57
+ getSchema(entity) {
58
+ const schema = this.schemas.get(entity);
59
+ if (!schema) {
60
+ throw new Error(`EntitySchemaRegistry: No schema registered for entity '${entity}'. ` +
61
+ `Available entities: ${Array.from(this.schemas.keys()).join(", ") || "none"}`);
62
+ }
63
+ return schema;
64
+ }
65
+ /**
66
+ * Checks if an entity is registered.
67
+ * @param entity - Entity name.
68
+ */
69
+ has(entity) {
70
+ return this.schemas.has(entity);
71
+ }
72
+ /**
73
+ * Gets the table name for an entity.
74
+ * @param entity - Entity name.
75
+ */
76
+ getTable(entity) {
77
+ return this.getSchema(entity).table;
78
+ }
79
+ /**
80
+ * Gets the field mapping for an entity.
81
+ * @param entity - Entity name.
82
+ */
83
+ getFieldsMap(entity) {
84
+ return this.getSchema(entity).fields || {};
85
+ }
86
+ /**
87
+ * Maps a domain field name to the database field name.
88
+ * @param entity - Entity name.
89
+ * @param fieldName - Domain field name.
90
+ */
91
+ mapFieldName(entity, fieldName) {
92
+ const fields = this.getFieldsMap(entity);
93
+ return fields[fieldName] ?? fieldName;
94
+ }
95
+ /**
96
+ * Maps fields of a domain object to database field names.
97
+ * Ignores values that are Entity, ValueObject, or Arrays.
98
+ *
99
+ * @param entity - Entity name.
100
+ * @param data - Data to be mapped.
101
+ */
102
+ mapFields(entity, data) {
103
+ const fields = this.getFieldsMap(entity);
104
+ const result = {};
105
+ for (const [key, value] of Object.entries(data)) {
106
+ if (this.isEntityOrCollection(value)) {
107
+ continue;
108
+ }
109
+ const mappedKey = fields[key] ?? key;
110
+ result[mappedKey] = this.normalizeValue(value);
111
+ }
112
+ return result;
113
+ }
114
+ /**
115
+ * Maps a complete domain entity to database data.
116
+ * Used for CREATE operations.
117
+ *
118
+ * @param entity - Entity name.
119
+ * @param domainEntity - Domain entity instance.
120
+ */
121
+ mapEntity(entity, domainEntity) {
122
+ const fields = this.getFieldsMap(entity);
123
+ const result = {};
124
+ // Map ID if it is an Entity or has entity-like structure
125
+ const hasId = domainEntity.id;
126
+ if (hasId) {
127
+ // Extract id value
128
+ const idValue = hasId.value ?? hasId;
129
+ result["id"] = idValue;
130
+ }
131
+ // Get props
132
+ const props = domainEntity.props || domainEntity;
133
+ for (const [key, value] of Object.entries(props)) {
134
+ if (key === "id")
135
+ continue; // ID already mapped
136
+ if (this.isEntityOrCollection(value))
137
+ continue;
138
+ const mappedKey = fields[key] ?? key;
139
+ result[mappedKey] = this.normalizeValue(value);
140
+ }
141
+ return result;
142
+ }
143
+ /**
144
+ * Gets the FK object to relate with the parent.
145
+ *
146
+ * @param entity - Entity name.
147
+ * @param parentId - Parent ID.
148
+ * @returns Object with the FK field or null if there is no parent.
149
+ */
150
+ getParentFk(entity, parentId) {
151
+ const schema = this.getSchema(entity);
152
+ if (!schema.parentFk)
153
+ return null;
154
+ return { [schema.parentFk.field]: parentId };
155
+ }
156
+ /**
157
+ * Gets the name of the parent entity.
158
+ * @param entity - Entity name.
159
+ */
160
+ getParentEntity(entity) {
161
+ const schema = this.getSchema(entity);
162
+ return schema.parentFk?.parentEntity ?? null;
163
+ }
164
+ /**
165
+ * Gets the FK field name.
166
+ * @param entity - Entity name.
167
+ */
168
+ getParentFkField(entity) {
169
+ const schema = this.getSchema(entity);
170
+ return schema.parentFk?.field ?? null;
171
+ }
172
+ /**
173
+ * Lists all registered entities.
174
+ */
175
+ getRegisteredEntities() {
176
+ return Array.from(this.schemas.keys());
177
+ }
178
+ /**
179
+ * Clears all registered schemas.
180
+ */
181
+ clear() {
182
+ this.schemas.clear();
183
+ }
184
+ /**
185
+ * Checks if a value is Entity, ValueObject, or Array.
186
+ */
187
+ isEntityOrCollection(value) {
188
+ if (value === null || value === undefined)
189
+ return false;
190
+ if (Array.isArray(value))
191
+ return true;
192
+ if (value instanceof Entity)
193
+ return true;
194
+ if (value instanceof ValueObject)
195
+ return true;
196
+ // Checks if it has the structure of an Entity (object with 'id' that has 'value')
197
+ if (typeof value === 'object' && value.id && typeof value.id === 'object' && 'value' in value.id) {
198
+ return true;
199
+ }
200
+ return false;
201
+ }
202
+ /**
203
+ * Normalizes a value for persistence.
204
+ */
205
+ normalizeValue(value) {
206
+ if (value === null || value === undefined)
207
+ return value;
208
+ if (value instanceof Id)
209
+ return value.value;
210
+ if (value instanceof Date)
211
+ return value;
212
+ if (typeof value === "object" && "value" in value) {
213
+ // Might be an ID or other wrapper
214
+ return value.value;
215
+ }
216
+ return value;
217
+ }
218
+ }
219
+ //# sourceMappingURL=entity-schema-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-schema-registry.js","sourceRoot":"","sources":["../src/entity-schema-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ import { HistoryEntry } from "./types";
2
+ import { AggregateChanges } from "./aggregate-changes";
3
+ /**
4
+ * Callback for validation on property change.
5
+ * Return false to reject the change, or throw an error.
6
+ */
7
+ export type OnChangeValidator = (path: string, oldValue: any, newValue: any) => boolean | void;
8
+ /**
9
+ * Tracks changes in Aggregates using Proxy.
10
+ *
11
+ * Features:
12
+ * - Tracks changes in primitive properties
13
+ * - Tracks changes in nested entities (1:1)
14
+ * - Tracks changes in collections (1:N)
15
+ * - Supports Value Objects with identityKey
16
+ * - Calculates depth automatically
17
+ * - Generates AggregateChanges for persistence
18
+ * - Supports validation on change via onChangeValidator
19
+ */
20
+ export declare class HistoryTracker {
21
+ private target;
22
+ private rootEntityName;
23
+ private path;
24
+ private depth;
25
+ private parentId?;
26
+ private parentEntity?;
27
+ private rootTracker?;
28
+ private history;
29
+ private originalValues;
30
+ private trackedArrays;
31
+ private trackedEntities;
32
+ private onChangeValidator?;
33
+ constructor(target: any, rootEntityName: string, path?: string, depth?: number, parentId?: string | undefined, parentEntity?: string | undefined, rootTracker?: HistoryTracker | undefined);
34
+ /**
35
+ * Sets a validator callback that will be called on every property change.
36
+ * The validator can:
37
+ * - Return false to reject the change (value will be reverted)
38
+ * - Throw an error to reject the change with an error
39
+ * - Return true/undefined to accept the change
40
+ */
41
+ setOnChangeValidator(validator: OnChangeValidator): void;
42
+ private captureInitialState;
43
+ private captureEntityState;
44
+ private captureArrayState;
45
+ createProxy(): any;
46
+ private createArrayProxy;
47
+ /**
48
+ * Returns all detected changes as AggregateChanges.
49
+ */
50
+ getChanges<TEntityMap = Record<string, any>>(): AggregateChanges<TEntityMap>;
51
+ private analyzeRootChanges;
52
+ private analyzeCollectionChanges;
53
+ /**
54
+ * Recursively marks all nested items as created when a parent is created.
55
+ */
56
+ private markNestedItemsAsCreated;
57
+ /**
58
+ * Recursively marks all nested items as deleted when a parent is deleted.
59
+ * Uses the original captured state to find nested items.
60
+ */
61
+ private markNestedItemsAsDeleted;
62
+ /**
63
+ * Recursively marks nested items as deleted from a JSON object.
64
+ * This is used when processing cloned (JSON) state.
65
+ */
66
+ private markNestedJsonItemAsDeleted;
67
+ /**
68
+ * Extracts identity key from a JSON object by looking at the original ValueObject instances.
69
+ */
70
+ private extractIdentityKeyFromJson;
71
+ private collectNestedArrays;
72
+ private analyzeEntityChanges;
73
+ private detectEntityChangeState;
74
+ private detectArrayChanges;
75
+ private detectChangedFields;
76
+ private handleArrayAssignment;
77
+ private handleEntityChange;
78
+ private getRootTracker;
79
+ private buildPath;
80
+ private shouldSkipProperty;
81
+ private getValueAtPath;
82
+ private getItemKey;
83
+ private getEntityId;
84
+ private getEntityName;
85
+ private isEntityOrVO;
86
+ private isEqual;
87
+ private deepEqual;
88
+ private hasChanged;
89
+ private cloneArray;
90
+ private deepClone;
91
+ private normalizeAndStringify;
92
+ getHistory(): HistoryEntry[];
93
+ clearHistory(): void;
94
+ markAsClean(): void;
95
+ getTarget(): any;
96
+ }
97
+ //# sourceMappingURL=history-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-tracker.d.ts","sourceRoot":"","sources":["../src/history-tracker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,YAAY,EAAe,MAAM,SAAS,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,GAAG,KACV,OAAO,GAAG,IAAI,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;IAQvB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,YAAY,CAAC;IACrB,OAAO,CAAC,WAAW,CAAC;IAbtB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAsC;IAC3D,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,iBAAiB,CAAC,CAAoB;gBAGpC,MAAM,EAAE,GAAG,EACX,cAAc,EAAE,MAAM,EACtB,IAAI,GAAE,MAAW,EACjB,KAAK,GAAE,MAAU,EACjB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,YAAY,CAAC,EAAE,MAAM,YAAA,EACrB,WAAW,CAAC,EAAE,cAAc,YAAA;IAQtC;;;;;;OAMG;IACH,oBAAoB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAQxD,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,kBAAkB;IAgD1B,OAAO,CAAC,iBAAiB;IAwCzB,WAAW,IAAI,GAAG;IA6FlB,OAAO,CAAC,gBAAgB;IA0HxB;;OAEG;IACH,UAAU,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,gBAAgB,CAAC,UAAU,CAAC;IAW5E,OAAO,CAAC,kBAAkB;IAgC1B,OAAO,CAAC,wBAAwB;IAuEhC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAwChC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAyChC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAoDnC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAuBlC,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,oBAAoB;IA4E5B,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,kBAAkB;IA2C1B,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,SAAS;IA4CjB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,SAAS;IAkCjB,OAAO,CAAC,qBAAqB;IAkB7B,UAAU,IAAI,YAAY,EAAE;IAI5B,YAAY,IAAI,IAAI;IASpB,WAAW,IAAI,IAAI;IAInB,SAAS,IAAI,GAAG;CAGjB"}