@woltz/rich-domain 1.2.1 → 1.2.2

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 (91) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/base-entity.d.ts +1 -1
  3. package/dist/base-entity.d.ts.map +1 -1
  4. package/dist/base-entity.js +3 -41
  5. package/dist/base-entity.js.map +1 -1
  6. package/dist/{history-tracker.d.ts → change-tracker.d.ts} +3 -3
  7. package/dist/change-tracker.d.ts.map +1 -0
  8. package/dist/{history-tracker.js → change-tracker.js} +9 -56
  9. package/dist/change-tracker.js.map +1 -0
  10. package/dist/constants.d.ts +7 -1
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +65 -0
  13. package/dist/constants.js.map +1 -1
  14. package/dist/criteria.d.ts.map +1 -1
  15. package/dist/criteria.js +6 -4
  16. package/dist/criteria.js.map +1 -1
  17. package/dist/domain-event.d.ts.map +1 -1
  18. package/dist/domain-event.js +0 -3
  19. package/dist/domain-event.js.map +1 -1
  20. package/dist/entity-changes.d.ts.map +1 -1
  21. package/dist/entity-changes.js +0 -4
  22. package/dist/entity-changes.js.map +1 -1
  23. package/dist/entity-schema-registry.d.ts.map +1 -1
  24. package/dist/entity-schema-registry.js +2 -8
  25. package/dist/entity-schema-registry.js.map +1 -1
  26. package/dist/entity.d.ts +0 -6
  27. package/dist/entity.d.ts.map +1 -1
  28. package/dist/entity.js +0 -9
  29. package/dist/entity.js.map +1 -1
  30. package/dist/index.d.ts +9 -6
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +8 -12
  33. package/dist/index.js.map +1 -1
  34. package/dist/paginated-result.d.ts.map +1 -1
  35. package/dist/paginated-result.js +0 -15
  36. package/dist/paginated-result.js.map +1 -1
  37. package/dist/repository/base-repository.d.ts +1 -1
  38. package/dist/repository/base-repository.d.ts.map +1 -1
  39. package/dist/repository/index.d.ts.map +1 -1
  40. package/dist/repository/index.js +0 -6
  41. package/dist/repository/index.js.map +1 -1
  42. package/dist/repository/unit-of-work.d.ts.map +1 -1
  43. package/dist/repository/unit-of-work.js +0 -3
  44. package/dist/repository/unit-of-work.js.map +1 -1
  45. package/dist/types/change-tracker.d.ts +10 -0
  46. package/dist/types/change-tracker.d.ts.map +1 -1
  47. package/dist/types/domain.d.ts +4 -6
  48. package/dist/types/domain.d.ts.map +1 -1
  49. package/dist/types/index.d.ts +1 -1
  50. package/dist/types/index.d.ts.map +1 -1
  51. package/dist/types/index.js +1 -1
  52. package/dist/types/index.js.map +1 -1
  53. package/dist/utils/criteria-operator-validation.d.ts +1 -0
  54. package/dist/utils/criteria-operator-validation.d.ts.map +1 -1
  55. package/dist/utils/criteria-operator-validation.js +39 -17
  56. package/dist/utils/criteria-operator-validation.js.map +1 -1
  57. package/dist/validation-error.d.ts.map +1 -1
  58. package/dist/validation-error.js +1 -3
  59. package/dist/validation-error.js.map +1 -1
  60. package/dist/value-object.d.ts +1 -1
  61. package/dist/value-object.d.ts.map +1 -1
  62. package/dist/value-object.js +0 -1
  63. package/dist/value-object.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/base-entity.ts +4 -51
  66. package/src/{history-tracker.ts → change-tracker.ts} +20 -72
  67. package/src/constants.ts +75 -1
  68. package/src/criteria.ts +9 -3
  69. package/src/domain-event.ts +0 -4
  70. package/src/entity-changes.ts +0 -5
  71. package/src/entity-schema-registry.ts +2 -22
  72. package/src/entity.ts +0 -11
  73. package/src/index.ts +15 -20
  74. package/src/paginated-result.ts +0 -21
  75. package/src/repository/base-repository.ts +1 -1
  76. package/src/repository/index.ts +0 -9
  77. package/src/repository/unit-of-work.ts +0 -4
  78. package/src/types/change-tracker.ts +16 -4
  79. package/src/types/domain.ts +4 -8
  80. package/src/types/index.ts +1 -1
  81. package/src/utils/criteria-operator-validation.ts +57 -19
  82. package/src/validation-error.ts +1 -3
  83. package/src/value-object.ts +1 -2
  84. package/tests/history-tracker.spec.ts +1 -1
  85. package/dist/history-tracker.d.ts.map +0 -1
  86. package/dist/history-tracker.js.map +0 -1
  87. package/dist/types/history-tracker.d.ts +0 -47
  88. package/dist/types/history-tracker.d.ts.map +0 -1
  89. package/dist/types/history-tracker.js +0 -2
  90. package/dist/types/history-tracker.js.map +0 -1
  91. package/src/types/history-tracker.ts +0 -58
@@ -27,7 +27,7 @@ export type OnChangeValidator = (
27
27
  * - Generates AggregateChanges for persistence
28
28
  * - Supports validation on change via onChangeValidator
29
29
  */
30
- export class HistoryTracker {
30
+ export class ChangeTracker {
31
31
  private history: HistoryEntry[] = [];
32
32
  private originalValues: Map<string, any> = new Map();
33
33
  private trackedArrays: Map<string, ArrayState> = new Map();
@@ -41,7 +41,7 @@ export class HistoryTracker {
41
41
  private depth: number = 0,
42
42
  private parentId?: string,
43
43
  private parentEntity?: string,
44
- private rootTracker?: HistoryTracker
44
+ private rootTracker?: ChangeTracker
45
45
  ) {
46
46
  if (!rootTracker) {
47
47
  this.rootTracker = this;
@@ -60,10 +60,6 @@ export class HistoryTracker {
60
60
  this.getRootTracker().onChangeValidator = validator;
61
61
  }
62
62
 
63
- // ============================================================================
64
- // Initial State Capture
65
- // ============================================================================
66
-
67
63
  private captureInitialState(): void {
68
64
  if (this.depth > 0) return;
69
65
  this.captureEntityState(this.target, this.rootEntityName, "", 0);
@@ -153,10 +149,6 @@ export class HistoryTracker {
153
149
  });
154
150
  }
155
151
 
156
- // ============================================================================
157
- // Proxy Creation
158
- // ============================================================================
159
-
160
152
  createProxy(): any {
161
153
  const handler: ProxyHandler<any> = {
162
154
  get: (target, prop, receiver) => {
@@ -177,7 +169,7 @@ export class HistoryTracker {
177
169
  }
178
170
 
179
171
  if (this.isEntityOrVO(value)) {
180
- const nestedTracker = new HistoryTracker(
172
+ const nestedTracker = new ChangeTracker(
181
173
  value,
182
174
  this.getEntityName(value),
183
175
  currentPath,
@@ -200,7 +192,6 @@ export class HistoryTracker {
200
192
  return true;
201
193
  }
202
194
 
203
- // Call validator before making the change
204
195
  const rootTracker = this.getRootTracker();
205
196
  if (rootTracker.onChangeValidator) {
206
197
  try {
@@ -210,21 +201,17 @@ export class HistoryTracker {
210
201
  newValue
211
202
  );
212
203
  if (result === false) {
213
- // Validator rejected the change
214
- return true; // Return true to not throw, but don't apply change
204
+ return true;
215
205
  }
216
206
  } catch (error) {
217
- // Validator threw an error - propagate it
218
207
  throw error;
219
208
  }
220
209
  }
221
210
 
222
- // Store original value
223
211
  if (!rootTracker.originalValues.has(currentPath)) {
224
212
  rootTracker.originalValues.set(currentPath, oldValue);
225
213
  }
226
214
 
227
- // Record in history
228
215
  rootTracker.history.push({
229
216
  path: currentPath,
230
217
  previousValue: oldValue,
@@ -234,7 +221,6 @@ export class HistoryTracker {
234
221
 
235
222
  const result = Reflect.set(target, prop, newValue, receiver);
236
223
 
237
- // Handle special cases
238
224
  if (Array.isArray(newValue)) {
239
225
  this.handleArrayAssignment(currentPath, oldValue);
240
226
  } else if (this.isEntityOrVO(newValue) || this.isEntityOrVO(oldValue)) {
@@ -284,14 +270,12 @@ export class HistoryTracker {
284
270
  return function (...args: any[]) {
285
271
  const oldArray = target.slice();
286
272
 
287
- // Call validator before array mutation
288
273
  if (rootTracker.onChangeValidator) {
289
274
  try {
290
- const result = rootTracker.onChangeValidator(
291
- path,
292
- oldArray,
293
- [...oldArray, ...args] // Preview of change
294
- );
275
+ const result = rootTracker.onChangeValidator(path, oldArray, [
276
+ ...oldArray,
277
+ ...args,
278
+ ]);
295
279
  if (result === false) {
296
280
  return undefined;
297
281
  }
@@ -317,7 +301,7 @@ export class HistoryTracker {
317
301
 
318
302
  if (!isNaN(Number(prop)) && tracker.isEntityOrVO(value)) {
319
303
  const nestedPath = `${path}[${String(prop)}]`;
320
- const nestedTracker = new HistoryTracker(
304
+ const nestedTracker = new ChangeTracker(
321
305
  value,
322
306
  tracker.getEntityName(value),
323
307
  nestedPath,
@@ -336,7 +320,6 @@ export class HistoryTracker {
336
320
  if (!isNaN(Number(prop))) {
337
321
  const oldArray = target.slice();
338
322
 
339
- // Call validator before array item change
340
323
  if (rootTracker.onChangeValidator) {
341
324
  try {
342
325
  const result = rootTracker.onChangeValidator(
@@ -368,10 +351,6 @@ export class HistoryTracker {
368
351
  });
369
352
  }
370
353
 
371
- // ============================================================================
372
- // getChanges() - Main Method
373
- // ============================================================================
374
-
375
354
  /**
376
355
  * Returns all detected changes as AggregateChanges.
377
356
  */
@@ -388,7 +367,7 @@ export class HistoryTracker {
388
367
 
389
368
  private analyzeRootChanges(
390
369
  changes: AggregateChanges<any>,
391
- rootTracker: HistoryTracker
370
+ rootTracker: ChangeTracker
392
371
  ): void {
393
372
  const changedFields: Record<string, any> = {};
394
373
  let hasChanges = false;
@@ -420,7 +399,7 @@ export class HistoryTracker {
420
399
 
421
400
  private analyzeCollectionChanges(
422
401
  changes: AggregateChanges<any>,
423
- rootTracker: HistoryTracker
402
+ rootTracker: ChangeTracker
424
403
  ): void {
425
404
  const allTrackedArrays = new Map<string, ArrayState>();
426
405
  const processedArrays = new Set<any>();
@@ -456,7 +435,6 @@ export class HistoryTracker {
456
435
  const itemEntityName = this.getEntityName(item);
457
436
  changes.addCreate(itemEntityName, item, depth, parentId, parentEntity);
458
437
 
459
- // Recursively mark nested items as created
460
438
  this.markNestedItemsAsCreated(item, depth, changes);
461
439
  }
462
440
 
@@ -482,7 +460,6 @@ export class HistoryTracker {
482
460
  const deleteId = id || key!;
483
461
  changes.addDelete(itemEntityName, deleteId, item, depth);
484
462
 
485
- // Recursively mark nested items as deleted using ORIGINAL state
486
463
  this.markNestedItemsAsDeleted(item, depth, changes, rootTracker);
487
464
  }
488
465
  }
@@ -508,7 +485,6 @@ export class HistoryTracker {
508
485
  if (propName === "id") continue;
509
486
 
510
487
  if (Array.isArray(value)) {
511
- // Process all items in the array
512
488
  for (const nestedItem of value) {
513
489
  if (this.isEntityOrVO(nestedItem)) {
514
490
  const nestedId = this.getEntityId(nestedItem);
@@ -523,8 +499,11 @@ export class HistoryTracker {
523
499
  this.getEntityName(item)
524
500
  );
525
501
 
526
- // Recursively process nested items
527
- this.markNestedItemsAsCreated(nestedItem, parentDepth + 1, changes);
502
+ this.markNestedItemsAsCreated(
503
+ nestedItem,
504
+ parentDepth + 1,
505
+ changes
506
+ );
528
507
  }
529
508
  }
530
509
  }
@@ -540,22 +519,16 @@ export class HistoryTracker {
540
519
  item: any,
541
520
  parentDepth: number,
542
521
  changes: AggregateChanges<any>,
543
- rootTracker: HistoryTracker
522
+ rootTracker: ChangeTracker
544
523
  ): void {
545
524
  if (!item || typeof item !== "object") return;
546
525
 
547
- // Get the ID to look up the original state
548
526
  const itemId = this.getEntityId(item);
549
527
  if (!itemId) return;
550
528
 
551
- // Look through all tracked arrays to find nested items
552
529
  for (const [, arrayState] of rootTracker.trackedArrays) {
553
- // Check if this array belongs to our deleted item
554
530
  if (arrayState.metadata.parentId === itemId) {
555
- // Use the CLONED (original) state to get the items
556
- // Note: cloned items are JSON objects, not Entity/VO instances
557
531
  for (const nestedItem of arrayState.cloned) {
558
- // Cloned items are JSON objects with an 'id' property
559
532
  const id =
560
533
  typeof nestedItem === "object" && nestedItem !== null
561
534
  ? nestedItem.id
@@ -564,7 +537,6 @@ export class HistoryTracker {
564
537
  const entityName = arrayState.metadata.entityName;
565
538
  changes.addDelete(entityName, id, nestedItem, parentDepth + 1);
566
539
 
567
- // Recursively process this item's nested arrays
568
540
  this.markNestedJsonItemAsDeleted(
569
541
  id,
570
542
  parentDepth + 1,
@@ -585,12 +557,10 @@ export class HistoryTracker {
585
557
  itemId: string,
586
558
  parentDepth: number,
587
559
  changes: AggregateChanges<any>,
588
- rootTracker: HistoryTracker
560
+ rootTracker: ChangeTracker
589
561
  ): void {
590
- // Look through all tracked arrays to find nested items of this parent
591
562
  for (const [, arrayState] of rootTracker.trackedArrays) {
592
563
  if (arrayState.metadata.parentId === itemId) {
593
- // Process all items in this nested array
594
564
  for (const nestedJsonItem of arrayState.cloned) {
595
565
  if (typeof nestedJsonItem !== "object" || nestedJsonItem === null)
596
566
  continue;
@@ -606,7 +576,6 @@ export class HistoryTracker {
606
576
  parentDepth + 1
607
577
  );
608
578
 
609
- // Recursively process further nesting
610
579
  this.markNestedJsonItemAsDeleted(
611
580
  nestedId,
612
581
  parentDepth + 1,
@@ -614,7 +583,6 @@ export class HistoryTracker {
614
583
  rootTracker
615
584
  );
616
585
  } else {
617
- // Value object - try to extract identity key
618
586
  const key = this.extractIdentityKeyFromJson(
619
587
  nestedJsonItem,
620
588
  arrayState.original
@@ -640,20 +608,16 @@ export class HistoryTracker {
640
608
  jsonItem: any,
641
609
  originalArray: any[]
642
610
  ): string | undefined {
643
- // Try to find the original ValueObject to get its identity key
644
611
  for (const originalItem of originalArray) {
645
612
  if (this.isEntityOrVO(originalItem)) {
646
613
  const originalJson = this.deepClone(originalItem);
647
- // Check if this matches our JSON item (rough comparison)
648
614
  if (JSON.stringify(originalJson) === JSON.stringify(jsonItem)) {
649
- // Found the matching original item - extract its identity key
650
615
  const key = this.getItemKey(originalItem);
651
616
  if (key) return key;
652
617
  }
653
618
  }
654
619
  }
655
620
 
656
- // Fallback: if it has an id, use that
657
621
  if (jsonItem.id) return jsonItem.id;
658
622
 
659
623
  return undefined;
@@ -692,7 +656,7 @@ export class HistoryTracker {
692
656
 
693
657
  private analyzeEntityChanges(
694
658
  changes: AggregateChanges<any>,
695
- rootTracker: HistoryTracker
659
+ rootTracker: ChangeTracker
696
660
  ): void {
697
661
  for (const [path, trackedItem] of rootTracker.trackedEntities) {
698
662
  if (path === "root") continue;
@@ -720,7 +684,6 @@ export class HistoryTracker {
720
684
  case "deleted":
721
685
  const id = this.getEntityId(originalValue);
722
686
  if (id) {
723
- // Use originalEntity instead of originalValue to preserve entity instance
724
687
  changes.addDelete(entityName, id, originalEntity, depth);
725
688
  }
726
689
  break;
@@ -728,7 +691,6 @@ export class HistoryTracker {
728
691
  case "replaced":
729
692
  const oldId = this.getEntityId(originalValue);
730
693
  if (oldId) {
731
- // Use originalEntity instead of originalValue to preserve entity instance
732
694
  changes.addDelete(entityName, oldId, originalEntity, depth);
733
695
  }
734
696
  changes.addCreate(
@@ -762,10 +724,6 @@ export class HistoryTracker {
762
724
  }
763
725
  }
764
726
 
765
- // ============================================================================
766
- // Change Detection Helpers
767
- // ============================================================================
768
-
769
727
  private detectEntityChangeState(
770
728
  previous: any,
771
729
  current: any
@@ -864,10 +822,6 @@ export class HistoryTracker {
864
822
  return changes;
865
823
  }
866
824
 
867
- // ============================================================================
868
- // Internal Handlers
869
- // ============================================================================
870
-
871
825
  private handleArrayAssignment(path: string, oldValue: any): void {
872
826
  const rootTracker = this.getRootTracker();
873
827
 
@@ -892,7 +846,6 @@ export class HistoryTracker {
892
846
  const existingTracked = rootTracker.trackedEntities.get(path);
893
847
 
894
848
  rootTracker.trackedEntities.set(path, {
895
- // Preserve original entity, or use oldValue if this is the first change
896
849
  entity: existingTracked?.entity || oldValue,
897
850
  metadata: {
898
851
  entityName,
@@ -901,16 +854,11 @@ export class HistoryTracker {
901
854
  parentEntity: this.rootEntityName,
902
855
  path,
903
856
  },
904
- // Preserve original state
905
857
  originalState: existingTracked?.originalState,
906
858
  });
907
859
  }
908
860
 
909
- // ============================================================================
910
- // Utility Methods
911
- // ============================================================================
912
-
913
- private getRootTracker(): HistoryTracker {
861
+ private getRootTracker(): ChangeTracker {
914
862
  return this.rootTracker || this;
915
863
  }
916
864
 
package/src/constants.ts CHANGED
@@ -1,7 +1,81 @@
1
- import { ValidationConfig } from ".";
1
+ import {
2
+ ArrayOperators,
3
+ BooleanOperators,
4
+ DateOperators,
5
+ FilterOperator,
6
+ NumberOperators,
7
+ StringOperators,
8
+ ValidationConfig,
9
+ } from ".";
2
10
 
3
11
  export const DEFAULT_VALIDATION_CONFIG: Required<ValidationConfig> = {
4
12
  onCreate: true,
5
13
  onUpdate: true,
6
14
  throwOnError: true,
7
15
  };
16
+
17
+ export const ARRAY_OPERATORS: ArrayOperators[] = [
18
+ "in",
19
+ "notIn",
20
+ "isNull",
21
+ "isNotNull",
22
+ ];
23
+ export const BOOLEAN_OPERATORS: BooleanOperators[] = [
24
+ "equals",
25
+ "notEquals",
26
+ "isNull",
27
+ "isNotNull",
28
+ ];
29
+ export const DATE_OPERATORS: DateOperators[] = [
30
+ "equals",
31
+ "notEquals",
32
+ "greaterThan",
33
+ "greaterThanOrEqual",
34
+ "lessThan",
35
+ "lessThanOrEqual",
36
+ "in",
37
+ "notIn",
38
+ "between",
39
+ "isNull",
40
+ "isNotNull",
41
+ ];
42
+ export const NUMBER_OPERATORS: NumberOperators[] = [
43
+ "equals",
44
+ "notEquals",
45
+ "greaterThan",
46
+ "greaterThanOrEqual",
47
+ "lessThan",
48
+ "lessThanOrEqual",
49
+ "in",
50
+ "notIn",
51
+ "between",
52
+ "isNull",
53
+ "isNotNull",
54
+ ];
55
+ export const STRING_OPERATORS: StringOperators[] = [
56
+ "equals",
57
+ "notEquals",
58
+ "contains",
59
+ "startsWith",
60
+ "endsWith",
61
+ "in",
62
+ "notIn",
63
+ "isNull",
64
+ "isNotNull",
65
+ ];
66
+ export const FILTER_OPERATORS: FilterOperator[] = [
67
+ "equals",
68
+ "notEquals",
69
+ "greaterThan",
70
+ "greaterThanOrEqual",
71
+ "lessThan",
72
+ "lessThanOrEqual",
73
+ "contains",
74
+ "startsWith",
75
+ "endsWith",
76
+ "in",
77
+ "notIn",
78
+ "between",
79
+ "isNull",
80
+ "isNotNull",
81
+ ];
package/src/criteria.ts CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  isValidOperatorForType,
20
20
  getValidOperatorsForType,
21
21
  isOperator,
22
+ sanitizeFieldValue,
22
23
  } from "./utils/criteria-operator-validation";
23
24
  import { parseQueryValue } from "./utils/helpers";
24
25
 
@@ -460,10 +461,15 @@ export class Criteria<T = any> {
460
461
  }
461
462
 
462
463
  private validateOperator(operator: FilterOperator, value: any): void {
463
- if (value !== undefined && !isValidOperatorForType(value, operator)) {
464
- const validOps = getValidOperatorsForType(value);
464
+ const sanitizedValue = sanitizeFieldValue(value, operator);
465
+
466
+ if (
467
+ sanitizedValue !== undefined &&
468
+ !isValidOperatorForType(sanitizedValue, operator)
469
+ ) {
470
+ const validOps = getValidOperatorsForType(sanitizedValue);
465
471
  throw new InvalidCriteriaError(
466
- `Operator "${operator}" is not valid for type "${typeof value}". Valid operators: ${validOps.join(
472
+ `Operator "${operator}" is not valid for type "${typeof sanitizedValue}". Valid operators: ${validOps.join(
467
473
  ", "
468
474
  )}`,
469
475
  operator
@@ -1,7 +1,3 @@
1
- // ============================================================================
2
- // Domain Events - Event-Driven Architecture Support
3
- // ============================================================================
4
-
5
1
  import { IDomainEvent } from ".";
6
2
  import { Id } from "./id";
7
3
 
@@ -1,8 +1,3 @@
1
- // ============================================================================
2
- // Entity Changes
3
- // Changes filtered by entity type
4
- // ============================================================================
5
-
6
1
  import {
7
2
  Operation,
8
3
  CreateOperation,
@@ -8,17 +8,14 @@ import { Id } from "./id";
8
8
  export interface EntitySchema {
9
9
  /** Entity name in the domain (e.g., 'User', 'Post') */
10
10
  entity: string;
11
-
12
11
  /** Table name in the database (e.g., 'users', 'blog_posts') */
13
12
  table: string;
14
-
15
13
  /**
16
14
  * Field mapping: domain → database.
17
15
  * Only include fields with different names.
18
16
  * @example { email: 'user_email', createdAt: 'created_at' }
19
17
  */
20
18
  fields?: Record<string, string>;
21
-
22
19
  /**
23
20
  * FK configuration for parent relation.
24
21
  */
@@ -148,15 +145,11 @@ export class EntitySchemaRegistry {
148
145
  mapFields(entity: string, data: Record<string, any>): MappedEntityData {
149
146
  const fields = this.getFieldsMap(entity);
150
147
  const result: MappedEntityData = {};
151
-
152
148
  for (const [key, value] of Object.entries(data)) {
153
- if (this.isEntityOrCollection(value)) {
154
- continue;
155
- }
149
+ if (this.isEntityOrCollection(value)) continue;
156
150
  const mappedKey = fields[key] ?? key;
157
151
  result[mappedKey] = this.normalizeValue(value);
158
152
  }
159
-
160
153
  return result;
161
154
  }
162
155
 
@@ -173,26 +166,18 @@ export class EntitySchemaRegistry {
173
166
  ): MappedEntityData {
174
167
  const fields = this.getFieldsMap(entity);
175
168
  const result: MappedEntityData = {};
176
-
177
- // Map ID if it is an Entity or has entity-like structure
178
169
  const hasId = (domainEntity as any).id;
179
170
  if (hasId) {
180
- // Extract id value
181
171
  const idValue = hasId.value ?? hasId;
182
172
  result["id"] = idValue;
183
173
  }
184
-
185
- // Get props
186
174
  const props = (domainEntity as any).props || domainEntity;
187
-
188
175
  for (const [key, value] of Object.entries(props)) {
189
- if (key === "id") continue; // ID already mapped
176
+ if (key === "id") continue;
190
177
  if (this.isEntityOrCollection(value)) continue;
191
-
192
178
  const mappedKey = fields[key] ?? key;
193
179
  result[mappedKey] = this.normalizeValue(value);
194
180
  }
195
-
196
181
  return result;
197
182
  }
198
183
 
@@ -206,7 +191,6 @@ export class EntitySchemaRegistry {
206
191
  getParentFk(entity: string, parentId: string): Record<string, string> | null {
207
192
  const schema = this.getSchema(entity);
208
193
  if (!schema.parentFk) return null;
209
-
210
194
  return { [schema.parentFk.field]: parentId };
211
195
  }
212
196
 
@@ -250,12 +234,9 @@ export class EntitySchemaRegistry {
250
234
  if (Array.isArray(value)) return true;
251
235
  if (value instanceof Entity) return true;
252
236
  if (value instanceof ValueObject) return true;
253
-
254
- // Checks if it has the structure of an Entity (object with 'id' that has 'value')
255
237
  if (typeof value === 'object' && value.id && typeof value.id === 'object' && 'value' in value.id) {
256
238
  return true;
257
239
  }
258
-
259
240
  return false;
260
241
  }
261
242
 
@@ -267,7 +248,6 @@ export class EntitySchemaRegistry {
267
248
  if (value instanceof Id) return value.value;
268
249
  if (value instanceof Date) return value;
269
250
  if (typeof value === "object" && "value" in value) {
270
- // Might be an ID or other wrapper
271
251
  return value.value;
272
252
  }
273
253
  return value;
package/src/entity.ts CHANGED
@@ -1,16 +1,5 @@
1
- // ============================================================================
2
- // Entity & Aggregate Classes
3
- // ============================================================================
4
-
5
1
  import { BaseEntity } from "./base-entity";
6
2
  import { BaseProps } from "./types";
7
3
 
8
- /**
9
- * Entity - Has identity and lifecycle, but is not an aggregate root
10
- */
11
4
  export class Entity<T extends BaseProps> extends BaseEntity<T> {}
12
-
13
- /**
14
- * Aggregate - Aggregate root that manages a consistency boundary
15
- */
16
5
  export class Aggregate<T extends BaseProps> extends BaseEntity<T> {}
package/src/index.ts CHANGED
@@ -1,29 +1,16 @@
1
- // ============================================================================
2
- // Rich Domain Library - Main Exports
3
- // ============================================================================
4
-
5
- // Core Classes
6
- export { Id } from "./id";
7
- export { Entity, Aggregate } from "./entity";
8
- export { ValueObject } from "./value-object";
9
- export { Mapper } from "./mapper";
10
- export { EntitySchemaRegistry } from "./entity-schema-registry";
11
-
12
1
  export * from "./validation-error";
13
-
14
- // Domain Events
15
2
  export * from "./domain-event";
16
3
  export * from "./domain-event-bus";
17
4
  export * from "./exceptions";
18
-
19
- // Criteria
20
5
  export * from "./criteria";
21
6
  export * from "./paginated-result";
22
-
23
- // Repository
24
7
  export * from "./repository";
25
-
26
- // Types
8
+ export { Id } from "./id";
9
+ export { Entity, Aggregate } from "./entity";
10
+ export { ValueObject } from "./value-object";
11
+ export { Mapper } from "./mapper";
12
+ export { EntitySchemaRegistry } from "./entity-schema-registry";
13
+ export { AggregateChanges } from "./aggregate-changes";
27
14
  export {
28
15
  DomainEventHandler,
29
16
  EntityHooks,
@@ -41,7 +28,6 @@ export {
41
28
  Order,
42
29
  IUnitOfWork,
43
30
  IDomainEventHandler,
44
- EntityId,
45
31
  FieldPath,
46
32
  FilterOperator,
47
33
  Search,
@@ -55,3 +41,12 @@ export {
55
41
  ArrayOperators,
56
42
  CriteriaOptions,
57
43
  } from "./types";
44
+ export {
45
+ ARRAY_OPERATORS,
46
+ BOOLEAN_OPERATORS,
47
+ DATE_OPERATORS,
48
+ NUMBER_OPERATORS,
49
+ STRING_OPERATORS,
50
+ FILTER_OPERATORS,
51
+ } from "./constants";
52
+ export { isValidOperatorForType } from "./utils/criteria-operator-validation";