@woltz/rich-domain 1.2.4 → 1.3.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/aggregate-changes.d.ts +56 -14
- package/dist/aggregate-changes.d.ts.map +1 -1
- package/dist/aggregate-changes.js +103 -23
- package/dist/aggregate-changes.js.map +1 -1
- package/dist/base-entity.d.ts +1 -1
- package/dist/base-entity.d.ts.map +1 -1
- package/dist/base-entity.js +28 -13
- package/dist/base-entity.js.map +1 -1
- package/dist/change-tracker.d.ts +2 -1
- package/dist/change-tracker.d.ts.map +1 -1
- package/dist/change-tracker.js +61 -35
- package/dist/change-tracker.js.map +1 -1
- package/dist/criteria.d.ts +7 -15
- package/dist/criteria.d.ts.map +1 -1
- package/dist/criteria.js +105 -81
- package/dist/criteria.js.map +1 -1
- package/dist/domain-event-bus.js +4 -4
- package/dist/domain-event-bus.js.map +1 -1
- package/dist/domain-event.js +3 -0
- package/dist/domain-event.js.map +1 -1
- package/dist/entity-changes.js +1 -0
- package/dist/entity-changes.js.map +1 -1
- package/dist/entity-schema-registry.d.ts +137 -3
- package/dist/entity-schema-registry.d.ts.map +1 -1
- package/dist/entity-schema-registry.js +160 -7
- package/dist/entity-schema-registry.js.map +1 -1
- package/dist/exceptions.js +26 -1
- package/dist/exceptions.js.map +1 -1
- package/dist/id.js +2 -0
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/paginated-result.d.ts +4 -4
- package/dist/paginated-result.d.ts.map +1 -1
- package/dist/paginated-result.js +14 -19
- package/dist/paginated-result.js.map +1 -1
- package/dist/repository/unit-of-work.js +3 -7
- package/dist/repository/unit-of-work.js.map +1 -1
- package/dist/types/change-tracker.d.ts +30 -0
- package/dist/types/change-tracker.d.ts.map +1 -1
- package/dist/types/criteria.d.ts +1 -4
- package/dist/types/criteria.d.ts.map +1 -1
- package/dist/types/domain.d.ts +2 -1
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/types/utils.d.ts +2 -2
- package/dist/utils/helpers.d.ts +1 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +23 -0
- package/dist/utils/helpers.js.map +1 -1
- package/dist/validation-error.d.ts +15 -1
- package/dist/validation-error.d.ts.map +1 -1
- package/dist/validation-error.js +46 -3
- package/dist/validation-error.js.map +1 -1
- package/dist/value-object.d.ts +1 -1
- package/dist/value-object.d.ts.map +1 -1
- package/dist/value-object.js +30 -2
- package/dist/value-object.js.map +1 -1
- package/package.json +17 -3
- package/src/aggregate-changes.ts +133 -24
- package/src/base-entity.ts +22 -11
- package/src/change-tracker.ts +113 -54
- package/src/criteria.ts +151 -109
- package/src/entity-schema-registry.ts +256 -6
- package/src/index.ts +1 -1
- package/src/paginated-result.ts +21 -29
- package/src/types/change-tracker.ts +31 -0
- package/src/types/criteria.ts +1 -4
- package/src/types/domain.ts +2 -1
- package/src/types/utils.ts +2 -2
- package/src/utils/helpers.ts +28 -0
- package/src/validation-error.ts +54 -4
- package/src/value-object.ts +6 -1
- package/.versionrc.json +0 -21
- package/CHANGELOG.md +0 -163
- package/tests/aggregate-changes.test.ts +0 -284
- package/tests/criteria.test.ts +0 -716
- package/tests/depth/deep-tracking.test.ts +0 -554
- package/tests/domain-events.test.ts +0 -431
- package/tests/entity-equality.test.ts +0 -464
- package/tests/entity-schema-registry.test.ts +0 -382
- package/tests/entity-validation.test.ts +0 -252
- package/tests/history-tracker.spec.ts +0 -439
- package/tests/id.test.ts +0 -338
- package/tests/load-test/data.json +0 -347211
- package/tests/load-test/entities.ts +0 -97
- package/tests/load-test/generate-data.ts +0 -81
- package/tests/load-test/lead-to-domain.mapper.ts +0 -24
- package/tests/load-test/load.test.ts +0 -38
- package/tests/repository.test.ts +0 -635
- package/tests/to-json.test.ts +0 -99
- package/tests/utils.ts +0 -290
- package/tests/value-object-validation.test.ts +0 -219
- package/tests/value-objects.test.ts +0 -80
- package/tsconfig.json +0 -9
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
// ============================================================================
|
|
2
|
-
// Tests: AggregateChanges
|
|
3
|
-
// ============================================================================
|
|
4
|
-
|
|
5
|
-
import { AggregateChanges } from "../src/aggregate-changes";
|
|
6
|
-
|
|
7
|
-
describe("AggregateChanges", () => {
|
|
8
|
-
let changes: AggregateChanges;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
changes = new AggregateChanges();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
describe("isEmpty / hasChanges", () => {
|
|
15
|
-
it("should be empty initially", () => {
|
|
16
|
-
expect(changes.isEmpty()).toBe(true);
|
|
17
|
-
expect(changes.hasChanges()).toBe(false);
|
|
18
|
-
expect(changes.count).toBe(0);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should not be empty after adding operation", () => {
|
|
22
|
-
changes.addCreate("User", { id: "1", name: "Test" }, 0);
|
|
23
|
-
expect(changes.isEmpty()).toBe(false);
|
|
24
|
-
expect(changes.hasChanges()).toBe(true);
|
|
25
|
-
expect(changes.count).toBe(1);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe("addCreate", () => {
|
|
30
|
-
it("should add create operation", () => {
|
|
31
|
-
const data = { id: "1", name: "Test User" };
|
|
32
|
-
changes.addCreate("User", data, 0);
|
|
33
|
-
|
|
34
|
-
expect(changes.hasCreates()).toBe(true);
|
|
35
|
-
expect(changes.creates()).toHaveLength(1);
|
|
36
|
-
expect(changes.creates()[0]).toMatchObject({
|
|
37
|
-
type: "create",
|
|
38
|
-
entity: "User",
|
|
39
|
-
data,
|
|
40
|
-
depth: 0,
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("should add create with parent info", () => {
|
|
45
|
-
const data = { id: "post-1", title: "Test Post" };
|
|
46
|
-
changes.addCreate("Post", data, 1, "user-1", "User");
|
|
47
|
-
|
|
48
|
-
const create = changes.creates()[0];
|
|
49
|
-
expect(create.parentId).toBe("user-1");
|
|
50
|
-
expect(create.parentEntity).toBe("User");
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("addUpdate", () => {
|
|
55
|
-
it("should add update operation", () => {
|
|
56
|
-
const data = { id: "1", name: "Updated" };
|
|
57
|
-
const changedFields = { name: "Updated" };
|
|
58
|
-
changes.addUpdate("User", "1", data, changedFields, 0);
|
|
59
|
-
|
|
60
|
-
expect(changes.hasUpdates()).toBe(true);
|
|
61
|
-
expect(changes.updates()).toHaveLength(1);
|
|
62
|
-
expect(changes.updates()[0]).toMatchObject({
|
|
63
|
-
type: "update",
|
|
64
|
-
entity: "User",
|
|
65
|
-
id: "1",
|
|
66
|
-
changedFields,
|
|
67
|
-
depth: 0,
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe("addDelete", () => {
|
|
73
|
-
it("should add delete operation", () => {
|
|
74
|
-
const data = { id: "1", name: "To Delete" };
|
|
75
|
-
changes.addDelete("User", "1", data, 0);
|
|
76
|
-
|
|
77
|
-
expect(changes.hasDeletes()).toBe(true);
|
|
78
|
-
expect(changes.deletes()).toHaveLength(1);
|
|
79
|
-
expect(changes.deletes()[0]).toMatchObject({
|
|
80
|
-
type: "delete",
|
|
81
|
-
entity: "User",
|
|
82
|
-
id: "1",
|
|
83
|
-
depth: 0,
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe("ordering", () => {
|
|
89
|
-
beforeEach(() => {
|
|
90
|
-
// Add operations in random order
|
|
91
|
-
changes.addCreate("Comment", { id: "c1" }, 2);
|
|
92
|
-
changes.addDelete("Like", "l1", { id: "l1" }, 3);
|
|
93
|
-
changes.addCreate("User", { id: "u1" }, 0);
|
|
94
|
-
changes.addDelete("Comment", "c2", { id: "c2" }, 2);
|
|
95
|
-
changes.addCreate("Post", { id: "p1" }, 1);
|
|
96
|
-
changes.addDelete("Post", "p2", { id: "p2" }, 1);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it("should order creates by depth ASC (root → leaf)", () => {
|
|
100
|
-
const creates = changes.creates();
|
|
101
|
-
expect(creates[0].entity).toBe("User"); // depth 0
|
|
102
|
-
expect(creates[1].entity).toBe("Post"); // depth 1
|
|
103
|
-
expect(creates[2].entity).toBe("Comment"); // depth 2
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("should order deletes by depth DESC (leaf → root)", () => {
|
|
107
|
-
const deletes = changes.deletes();
|
|
108
|
-
expect(deletes[0].entity).toBe("Like"); // depth 3
|
|
109
|
-
expect(deletes[1].entity).toBe("Comment"); // depth 2
|
|
110
|
-
expect(deletes[2].entity).toBe("Post"); // depth 1
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe("operations iterator", () => {
|
|
115
|
-
it("should yield operations in correct order: deletes, creates, updates", () => {
|
|
116
|
-
changes.addCreate("Post", { id: "p1" }, 1);
|
|
117
|
-
changes.addUpdate("User", "u1", { id: "u1" }, { name: "New" }, 0);
|
|
118
|
-
changes.addDelete("Comment", "c1", { id: "c1" }, 2);
|
|
119
|
-
|
|
120
|
-
const ops = [...changes.operations()];
|
|
121
|
-
|
|
122
|
-
expect(ops[0].type).toBe("delete"); // deletes first
|
|
123
|
-
expect(ops[1].type).toBe("create"); // creates second
|
|
124
|
-
expect(ops[2].type).toBe("update"); // updates last
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe("toBatchOperations", () => {
|
|
129
|
-
beforeEach(() => {
|
|
130
|
-
// Creates
|
|
131
|
-
changes.addCreate("User", { id: "u1" }, 0);
|
|
132
|
-
changes.addCreate("Post", { id: "p1" }, 1, "u1", "User");
|
|
133
|
-
changes.addCreate("Post", { id: "p2" }, 1, "u1", "User");
|
|
134
|
-
changes.addCreate("Comment", { id: "c1" }, 2, "p1", "Post");
|
|
135
|
-
|
|
136
|
-
// Updates
|
|
137
|
-
changes.addUpdate("User", "u2", { id: "u2" }, { name: "Updated" }, 0);
|
|
138
|
-
changes.addUpdate("Post", "p3", { id: "p3" }, { title: "New Title" }, 1);
|
|
139
|
-
|
|
140
|
-
// Deletes
|
|
141
|
-
changes.addDelete("Comment", "c2", { id: "c2" }, 2);
|
|
142
|
-
changes.addDelete("Comment", "c3", { id: "c3" }, 2);
|
|
143
|
-
changes.addDelete("Post", "p4", { id: "p4" }, 1);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("should group deletes by entity and order by depth DESC", () => {
|
|
147
|
-
const batch = changes.toBatchOperations();
|
|
148
|
-
|
|
149
|
-
expect(batch.deletes).toHaveLength(2); // Comment and Post
|
|
150
|
-
|
|
151
|
-
// Comments should come first (depth 2)
|
|
152
|
-
expect(batch.deletes[0].entity).toBe("Comment");
|
|
153
|
-
expect(batch.deletes[0].ids).toEqual(["c2", "c3"]);
|
|
154
|
-
|
|
155
|
-
// Posts second (depth 1)
|
|
156
|
-
expect(batch.deletes[1].entity).toBe("Post");
|
|
157
|
-
expect(batch.deletes[1].ids).toEqual(["p4"]);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("should group creates by entity and order by depth ASC", () => {
|
|
161
|
-
const batch = changes.toBatchOperations();
|
|
162
|
-
|
|
163
|
-
expect(batch.creates).toHaveLength(3); // User, Post, Comment
|
|
164
|
-
|
|
165
|
-
// User first (depth 0)
|
|
166
|
-
expect(batch.creates[0].entity).toBe("User");
|
|
167
|
-
expect(batch.creates[0].items).toHaveLength(1);
|
|
168
|
-
|
|
169
|
-
// Post second (depth 1)
|
|
170
|
-
expect(batch.creates[1].entity).toBe("Post");
|
|
171
|
-
expect(batch.creates[1].items).toHaveLength(2);
|
|
172
|
-
|
|
173
|
-
// Comment last (depth 2)
|
|
174
|
-
expect(batch.creates[2].entity).toBe("Comment");
|
|
175
|
-
expect(batch.creates[2].items).toHaveLength(1);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("should group updates by entity", () => {
|
|
179
|
-
const batch = changes.toBatchOperations();
|
|
180
|
-
|
|
181
|
-
expect(batch.updates).toHaveLength(2); // User and Post
|
|
182
|
-
|
|
183
|
-
const userUpdates = batch.updates.find((u) => u.entity === "User");
|
|
184
|
-
expect(userUpdates?.items).toHaveLength(1);
|
|
185
|
-
expect(userUpdates?.items[0].id).toBe("u2");
|
|
186
|
-
|
|
187
|
-
const postUpdates = batch.updates.find((u) => u.entity === "Post");
|
|
188
|
-
expect(postUpdates?.items).toHaveLength(1);
|
|
189
|
-
expect(postUpdates?.items[0].id).toBe("p3");
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should include parentId in create items", () => {
|
|
193
|
-
const batch = changes.toBatchOperations();
|
|
194
|
-
|
|
195
|
-
const postCreates = batch.creates.find((c) => c.entity === "Post");
|
|
196
|
-
expect(postCreates?.items[0].parentId).toBe("u1");
|
|
197
|
-
expect(postCreates?.items[1].parentId).toBe("u1");
|
|
198
|
-
|
|
199
|
-
const commentCreates = batch.creates.find((c) => c.entity === "Comment");
|
|
200
|
-
expect(commentCreates?.items[0].parentId).toBe("p1");
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
describe("for (filter by entity)", () => {
|
|
205
|
-
beforeEach(() => {
|
|
206
|
-
changes.addCreate("Post", { id: "p1", title: "Post 1" }, 1);
|
|
207
|
-
changes.addCreate("Post", { id: "p2", title: "Post 2" }, 1);
|
|
208
|
-
changes.addUpdate("Post", "p3", { id: "p3" }, { title: "Updated" }, 1);
|
|
209
|
-
changes.addDelete("Post", "p4", { id: "p4" }, 1);
|
|
210
|
-
changes.addCreate("Comment", { id: "c1" }, 2);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("should filter creates by entity", () => {
|
|
214
|
-
const postChanges = changes.for("Post");
|
|
215
|
-
expect(postChanges.creates).toHaveLength(2);
|
|
216
|
-
expect(postChanges.creates[0].id).toBe("p1");
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("should filter updates by entity", () => {
|
|
220
|
-
const postChanges = changes.for("Post");
|
|
221
|
-
expect(postChanges.updates).toHaveLength(1);
|
|
222
|
-
expect(postChanges.updates[0].entity.id).toBe("p3");
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it("should filter deletes by entity", () => {
|
|
226
|
-
const postChanges = changes.for("Post");
|
|
227
|
-
expect(postChanges.deletes).toHaveLength(1);
|
|
228
|
-
expect(postChanges.deletes[0].id).toBe("p4");
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it("should return empty for non-existent entity", () => {
|
|
232
|
-
const userChanges = changes.for("User");
|
|
233
|
-
expect(userChanges.isEmpty()).toBe(true);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("should have helper methods", () => {
|
|
237
|
-
const postChanges = changes.for("Post");
|
|
238
|
-
expect(postChanges.hasCreates()).toBe(true);
|
|
239
|
-
expect(postChanges.hasUpdates()).toBe(true);
|
|
240
|
-
expect(postChanges.hasDeletes()).toBe(true);
|
|
241
|
-
expect(postChanges.hasChanges()).toBe(true);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
describe("getAffectedEntities", () => {
|
|
246
|
-
it("should return list of unique entities", () => {
|
|
247
|
-
changes.addCreate("User", { id: "u1" }, 0);
|
|
248
|
-
changes.addCreate("Post", { id: "p1" }, 1);
|
|
249
|
-
changes.addUpdate("Post", "p2", { id: "p2" }, {}, 1);
|
|
250
|
-
changes.addDelete("Comment", "c1", { id: "c1" }, 2);
|
|
251
|
-
|
|
252
|
-
const entities = changes.getAffectedEntities();
|
|
253
|
-
|
|
254
|
-
expect(entities).toContain("User");
|
|
255
|
-
expect(entities).toContain("Post");
|
|
256
|
-
expect(entities).toContain("Comment");
|
|
257
|
-
expect(entities).toHaveLength(3);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
describe("clone", () => {
|
|
262
|
-
it("should create independent copy", () => {
|
|
263
|
-
changes.addCreate("User", { id: "u1" }, 0);
|
|
264
|
-
|
|
265
|
-
const cloned = changes.clone();
|
|
266
|
-
cloned.addCreate("Post", { id: "p1" }, 1);
|
|
267
|
-
|
|
268
|
-
expect(changes.count).toBe(1);
|
|
269
|
-
expect(cloned.count).toBe(2);
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
describe("clear", () => {
|
|
274
|
-
it("should remove all operations", () => {
|
|
275
|
-
changes.addCreate("User", { id: "u1" }, 0);
|
|
276
|
-
changes.addUpdate("Post", "p1", { id: "p1" }, {}, 1);
|
|
277
|
-
|
|
278
|
-
changes.clear();
|
|
279
|
-
|
|
280
|
-
expect(changes.isEmpty()).toBe(true);
|
|
281
|
-
expect(changes.count).toBe(0);
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
});
|