@woltz/rich-domain 1.2.1 → 1.2.4

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 (93) hide show
  1. package/CHANGELOG.md +56 -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 +13 -46
  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} +11 -57
  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 +13 -56
  66. package/src/{history-tracker.ts → change-tracker.ts} +23 -73
  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/depth/deep-tracking.test.ts +554 -0
  85. package/tests/history-tracker.spec.ts +1 -1
  86. package/tests/load-test/data.json +248187 -247017
  87. package/dist/history-tracker.d.ts.map +0 -1
  88. package/dist/history-tracker.js.map +0 -1
  89. package/dist/types/history-tracker.d.ts +0 -47
  90. package/dist/types/history-tracker.d.ts.map +0 -1
  91. package/dist/types/history-tracker.js +0 -2
  92. package/dist/types/history-tracker.js.map +0 -1
  93. package/src/types/history-tracker.ts +0 -58
@@ -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";
@@ -2,10 +2,6 @@ import { Id } from "./id";
2
2
  import type { Criteria } from "./criteria";
3
3
  import type { Pagination, PaginationMeta, Filter } from "./types";
4
4
 
5
- // ============================================================================
6
- // Type Utilities
7
- // ============================================================================
8
-
9
5
  /**
10
6
  * Infers the JSON result type from T
11
7
  * - If T has toJson(), returns its return type
@@ -21,10 +17,6 @@ export type PaginatedJsonResult<T> = {
21
17
  meta: PaginationMeta;
22
18
  };
23
19
 
24
- // ============================================================================
25
- // PaginatedResult Class
26
- // ============================================================================
27
-
28
20
  export class PaginatedResult<T> {
29
21
  constructor(
30
22
  public readonly data: T[],
@@ -78,13 +70,11 @@ export class PaginatedResult<T> {
78
70
  total = result.length;
79
71
  }
80
72
 
81
- // Apply filters
82
73
  for (const filter of criteria.getFilters()) {
83
74
  result = result.filter((item) => applyFilter(item, filter));
84
75
  total = result.length;
85
76
  }
86
77
 
87
- // Apply ordering
88
78
  for (const order of criteria.getOrders().reverse()) {
89
79
  result.sort((a, b) => {
90
80
  const aVal = getNestedValue(a, order.field);
@@ -98,7 +88,6 @@ export class PaginatedResult<T> {
98
88
  });
99
89
  }
100
90
 
101
- // Apply pagination
102
91
  const pagination = criteria.getPagination();
103
92
  if (pagination && !criteria.hasSearch()) {
104
93
  result = result.slice(
@@ -108,7 +97,6 @@ export class PaginatedResult<T> {
108
97
  return PaginatedResult.create(result, pagination, total);
109
98
  }
110
99
 
111
- // No pagination - return all with default meta
112
100
  return PaginatedResult.create(
113
101
  result,
114
102
  { page: 1, limit: result.length, offset: 0 },
@@ -140,20 +128,16 @@ export class PaginatedResult<T> {
140
128
  private deepSerialize(obj: any): any {
141
129
  if (obj === null || obj === undefined) return obj;
142
130
 
143
- // Id → string
144
131
  if (obj instanceof Id) return obj.value;
145
132
 
146
- // Arrays → map recursively
147
133
  if (Array.isArray(obj)) {
148
134
  return obj.map((item) => this.deepSerialize(item));
149
135
  }
150
136
 
151
- // Objects with toJson() method (Entity/Aggregate/ValueObject)
152
137
  if (obj && typeof obj.toJson === "function") {
153
138
  return obj.toJson();
154
139
  }
155
140
 
156
- // Plain objects → serialize properties recursively
157
141
  if (typeof obj === "object") {
158
142
  const result: any = {};
159
143
  for (const key in obj) {
@@ -164,7 +148,6 @@ export class PaginatedResult<T> {
164
148
  return result;
165
149
  }
166
150
 
167
- // Primitives
168
151
  return obj;
169
152
  }
170
153
 
@@ -190,10 +173,6 @@ export class PaginatedResult<T> {
190
173
  }
191
174
  }
192
175
 
193
- // ============================================================================
194
- // Helper Functions (moved from criteria.ts)
195
- // ============================================================================
196
-
197
176
  function applyFilter<T>(item: T, filter: Filter): boolean {
198
177
  const value = getNestedValue(item, filter.field);
199
178
 
@@ -29,5 +29,5 @@ export abstract class Repository<
29
29
  > extends WriteAndRead<TDomain> {
30
30
  protected abstract readonly mapperToDomain: Mapper<unknown, TDomain>;
31
31
  protected abstract readonly mapperToPersistence: Mapper<TDomain, unknown>;
32
- abstract get model(): any;
32
+ protected abstract get model(): any;
33
33
  }
@@ -1,12 +1,3 @@
1
- // ============================================================================
2
- // Repository Module - Clean exports
3
- // ============================================================================
4
-
5
- // Mapper
6
1
  export { Mapper } from "../mapper";
7
-
8
- // Base implementations
9
2
  export * from "./base-repository";
10
-
11
- // Unit of Work
12
3
  export { UnitOfWork, BaseTransactionContext } from "./unit-of-work";
@@ -1,7 +1,3 @@
1
- // ============================================================================
2
- // Unit of Work - Simple transaction management
3
- // ============================================================================
4
-
5
1
  import type { IUnitOfWork, TransactionContext } from "../types";
6
2
 
7
3
  /**
@@ -126,10 +126,10 @@ export interface CollectionChanges<T = any> {
126
126
  * Possible states for a 1:1 relationship.
127
127
  */
128
128
  export type EntityChangeState =
129
- | "created" // null → Entity
130
- | "updated" // Entity(id:1) → Entity(id:1) with changes
131
- | "deleted" // Entity → null
132
- | "replaced" // Entity(id:1) → Entity(id:2)
129
+ | "created" // null → Entity
130
+ | "updated" // Entity(id:1) → Entity(id:1) with changes
131
+ | "deleted" // Entity → null
132
+ | "replaced" // Entity(id:1) → Entity(id:2)
133
133
  | "unchanged"; // No changes
134
134
 
135
135
  /**
@@ -219,3 +219,15 @@ export interface TrackedEntityMetadata {
219
219
  /** Path in the object (e.g., 'posts[0].comments[1]') */
220
220
  path: string;
221
221
  }
222
+
223
+ export interface TrackedItem {
224
+ entity: any;
225
+ metadata: TrackedEntityMetadata;
226
+ originalState: any;
227
+ }
228
+
229
+ export interface ArrayState {
230
+ cloned: any[];
231
+ original: any[];
232
+ metadata: TrackedEntityMetadata;
233
+ }
@@ -1,9 +1,6 @@
1
- import { ValidationConfig } from "..";
2
1
  import { Id } from "../id";
3
2
  import { StandardSchema } from "./standard-schema";
4
3
 
5
- export type EntityId = string | number;
6
-
7
4
  export interface BaseProps {
8
5
  id: Id;
9
6
  }
@@ -22,15 +19,14 @@ export interface VOHooks<T, E> {
22
19
  rules?: (entity: E) => void;
23
20
  }
24
21
 
25
- // Specialized hooks for entities (with BaseProps)
26
22
  export interface EntityHooks<T extends BaseProps, E> {
27
23
  onBeforeUpdate?: (entity: E, snapshot: T) => boolean;
28
24
  onCreate?: (entity: E) => void;
29
25
  rules?: (entity: E) => void;
30
26
  }
31
27
 
32
- export interface EntityConstructor<T extends BaseProps, E> {
33
- new (props: T): E;
34
- validation?: DomainValidation<T>;
35
- hooks?: EntityHooks<T, E>;
28
+ export interface ValidationConfig {
29
+ onCreate?: boolean;
30
+ onUpdate?: boolean;
31
+ throwOnError?: boolean;
36
32
  }
@@ -1,7 +1,7 @@
1
1
  export * from "./criteria";
2
2
  export * from "./domain";
3
- export * from "./history-tracker";
4
3
  export * from "./standard-schema";
5
4
  export * from "./utils";
6
5
  export * from "./unit-of-work";
7
6
  export * from "./domain-event";
7
+ export * from "./change-tracker";
@@ -8,28 +8,71 @@ import {
8
8
  StringOperators,
9
9
  } from "../types";
10
10
 
11
- export function isValidOperatorForType(
11
+ const FORCE_STRING_OPERATORS = new Set(["contains", "startsWith", "endsWith"]);
12
+
13
+ export function sanitizeFieldValue(
12
14
  value: unknown,
13
15
  operator: FilterOperator
14
- ): boolean {
15
- // Handle null/undefined
16
+ ): unknown {
16
17
  if (value === null || value === undefined) {
17
- return ["isNull", "isNotNull", "equals", "notEquals"].includes(operator);
18
+ return value;
19
+ }
20
+
21
+ if (Array.isArray(value)) {
22
+ return value.map((item) => sanitizeFieldValue(item, operator));
23
+ }
24
+
25
+ if (value instanceof Date) {
26
+ return value;
27
+ }
28
+
29
+ const stringValue = String(value).trim();
30
+
31
+ if (stringValue === "") {
32
+ return "";
33
+ }
34
+
35
+ if (operator && FORCE_STRING_OPERATORS.has(operator)) {
36
+ return stringValue;
37
+ }
38
+
39
+ if (stringValue === "true" || stringValue === "false") {
40
+ return stringValue === "true";
41
+ }
42
+
43
+ const numberValue = Number(stringValue);
44
+ if (!Number.isNaN(numberValue)) {
45
+ return numberValue;
46
+ }
47
+
48
+ const dateObj = new Date(stringValue);
49
+ if (!Number.isNaN(dateObj.getTime())) {
50
+ return dateObj;
18
51
  }
19
52
 
20
- // Special case: between operator with array [min, max]
21
- if (operator === "between" && Array.isArray(value) && value.length === 2) {
22
- // Validate based on the type of the first element
23
- const elementType = typeof value[0];
24
- if (elementType === "number" || value[0] instanceof Date) {
53
+ return stringValue;
54
+ }
55
+
56
+ export function isValidOperatorForType(
57
+ value: unknown,
58
+ operator: FilterOperator
59
+ ): boolean {
60
+ const sanitizedValue = sanitizeFieldValue(value, operator);
61
+
62
+ if (
63
+ operator === "between" &&
64
+ Array.isArray(sanitizedValue) &&
65
+ sanitizedValue.length === 2
66
+ ) {
67
+ const elementType = typeof sanitizedValue[0];
68
+ if (elementType === "number" || sanitizedValue[0] instanceof Date) {
25
69
  return true;
26
70
  }
27
71
  return false;
28
72
  }
29
73
 
30
- const valueType = typeof value;
74
+ const valueType = typeof sanitizedValue;
31
75
 
32
- // String operators
33
76
  if (valueType === "string") {
34
77
  const validOps: StringOperators[] = [
35
78
  "equals",
@@ -45,7 +88,6 @@ export function isValidOperatorForType(
45
88
  return validOps.includes(operator as StringOperators);
46
89
  }
47
90
 
48
- // Number operators
49
91
  if (valueType === "number") {
50
92
  const validOps: NumberOperators[] = [
51
93
  "equals",
@@ -63,7 +105,6 @@ export function isValidOperatorForType(
63
105
  return validOps.includes(operator as NumberOperators);
64
106
  }
65
107
 
66
- // Boolean operators
67
108
  if (valueType === "boolean") {
68
109
  const validOps: BooleanOperators[] = [
69
110
  "equals",
@@ -74,8 +115,7 @@ export function isValidOperatorForType(
74
115
  return validOps.includes(operator as BooleanOperators);
75
116
  }
76
117
 
77
- // Date operators
78
- if (value instanceof Date) {
118
+ if (sanitizedValue instanceof Date) {
79
119
  const validOps: DateOperators[] = [
80
120
  "equals",
81
121
  "notEquals",
@@ -92,13 +132,11 @@ export function isValidOperatorForType(
92
132
  return validOps.includes(operator as DateOperators);
93
133
  }
94
134
 
95
- // Array operators
96
- if (Array.isArray(value)) {
135
+ if (Array.isArray(sanitizedValue)) {
97
136
  const validOps: ArrayOperators[] = ["in", "notIn", "isNull", "isNotNull"];
98
137
  return validOps.includes(operator as ArrayOperators);
99
138
  }
100
139
 
101
- // For unknown types, allow all operators
102
140
  return true;
103
141
  }
104
142
 
@@ -168,4 +206,4 @@ export function getValidOperatorsForType(value: unknown): FilterOperator[] {
168
206
 
169
207
  export function isOperator(value: string): value is FilterOperator {
170
208
  return FILTER_OPERATORS.includes(value as FilterOperator);
171
- }
209
+ }
@@ -5,7 +5,7 @@ export interface ValidationIssue {
5
5
 
6
6
  export class ValidationError extends Error {
7
7
  public readonly issues: ValidationIssue[];
8
- public readonly __isValidationError = true; // Brand for identification
8
+ public readonly __isValidationError = true;
9
9
 
10
10
  constructor(issues: ValidationIssue[], message?: string) {
11
11
  const errorMessage =
@@ -14,7 +14,6 @@ export class ValidationError extends Error {
14
14
  this.name = 'ValidationError';
15
15
  this.issues = issues;
16
16
 
17
- // Maintain proper stack trace
18
17
  if (Error.captureStackTrace) {
19
18
  Error.captureStackTrace(this, ValidationError);
20
19
  }
@@ -27,7 +26,6 @@ export class ValidationError extends Error {
27
26
  if (error instanceof ValidationError) {
28
27
  return true;
29
28
  }
30
- // Check by duck typing for cross-module compatibility
31
29
  return (
32
30
  error instanceof Error &&
33
31
  error.name === 'ValidationError' &&
@@ -9,7 +9,6 @@ import {
9
9
  import { DEFAULT_VALIDATION_CONFIG } from "./constants";
10
10
  import { DomainError } from "./exceptions";
11
11
 
12
- // Helper to get static properties from constructor
13
12
  function getStaticProperty<T>(
14
13
  instance: any,
15
14
  propertyName: string
@@ -34,7 +33,7 @@ export abstract class ValueObject<T> {
34
33
 
35
34
  /**
36
35
  * Identity key for identification in collections.
37
- * Used by HistoryTracker to track changes in arrays of Value Objects.
36
+ * Used by ChangeTracker to track changes in arrays of Value Objects.
38
37
  *
39
38
  * @example
40
39
  * ```typescript