@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.
- package/CHANGELOG.md +33 -0
- package/dist/aggregate-changes.d.ts +164 -0
- package/dist/aggregate-changes.d.ts.map +1 -0
- package/dist/aggregate-changes.js +281 -0
- package/dist/aggregate-changes.js.map +1 -0
- package/dist/base-entity.d.ts +32 -8
- package/dist/base-entity.d.ts.map +1 -1
- package/dist/base-entity.js +117 -86
- package/dist/base-entity.js.map +1 -1
- package/dist/criteria.d.ts +3 -3
- package/dist/criteria.d.ts.map +1 -1
- package/dist/criteria.js.map +1 -1
- package/dist/crypto.d.ts +3 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +29 -0
- package/dist/crypto.js.map +1 -0
- package/dist/entity-changes.d.ts +84 -0
- package/dist/entity-changes.d.ts.map +1 -0
- package/dist/entity-changes.js +135 -0
- package/dist/entity-changes.js.map +1 -0
- package/dist/entity-schema-registry.d.ts +148 -0
- package/dist/entity-schema-registry.d.ts.map +1 -0
- package/dist/entity-schema-registry.js +219 -0
- package/dist/entity-schema-registry.js.map +1 -0
- package/dist/history-tracker.d.ts +97 -0
- package/dist/history-tracker.d.ts.map +1 -0
- package/dist/history-tracker.js +805 -0
- package/dist/history-tracker.js.map +1 -0
- package/dist/id.d.ts +11 -10
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +4 -28
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mapper.d.ts +1 -1
- package/dist/mapper.d.ts.map +1 -1
- package/dist/mapper.js.map +1 -1
- package/dist/repository/base-repository.d.ts +6 -32
- package/dist/repository/base-repository.d.ts.map +1 -1
- package/dist/repository/base-repository.js +0 -27
- package/dist/repository/base-repository.js.map +1 -1
- package/dist/repository/unit-of-work.d.ts +0 -25
- package/dist/repository/unit-of-work.d.ts.map +1 -1
- package/dist/repository/unit-of-work.js +0 -25
- package/dist/repository/unit-of-work.js.map +1 -1
- package/dist/types/change-tracker.d.ts +186 -0
- package/dist/types/change-tracker.d.ts.map +1 -0
- package/dist/types/change-tracker.js +2 -0
- package/dist/types/change-tracker.js.map +1 -0
- package/dist/types/criteria.d.ts +5 -1
- package/dist/types/criteria.d.ts.map +1 -1
- package/dist/types/history-tracker.d.ts +11 -0
- package/dist/types/history-tracker.d.ts.map +1 -1
- package/dist/types/utils.d.ts +0 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/validation-error.d.ts.map +1 -1
- package/dist/validation-error.js +0 -3
- package/dist/validation-error.js.map +1 -1
- package/dist/value-object.d.ts +57 -8
- package/dist/value-object.d.ts.map +1 -1
- package/dist/value-object.js +49 -21
- package/dist/value-object.js.map +1 -1
- package/package.json +2 -1
- package/src/aggregate-changes.ts +335 -0
- package/src/base-entity.ts +140 -100
- package/src/criteria.ts +2 -1
- package/src/crypto.ts +31 -0
- package/src/entity-changes.ts +151 -0
- package/src/entity-schema-registry.ts +275 -0
- package/src/history-tracker.ts +1114 -0
- package/src/id.ts +17 -26
- package/src/index.ts +1 -0
- package/src/mapper.ts +4 -1
- package/src/repository/base-repository.ts +6 -37
- package/src/repository/unit-of-work.ts +0 -25
- package/src/types/change-tracker.ts +221 -0
- package/src/types/criteria.ts +6 -1
- package/src/types/history-tracker.ts +13 -0
- package/src/types/utils.ts +0 -9
- package/src/validation-error.ts +0 -4
- package/src/value-object.ts +84 -23
- package/tests/aggregate-changes.test.ts +284 -0
- package/tests/criteria.test.ts +122 -161
- package/tests/entity-equality.test.ts +38 -61
- package/tests/entity-schema-registry.test.ts +382 -0
- package/tests/entity-validation.test.ts +7 -94
- package/tests/history-tracker.spec.ts +349 -617
- package/tests/id.test.ts +41 -44
- package/tests/load-test/data.json +346041 -0
- package/tests/load-test/entities.ts +97 -0
- package/tests/load-test/generate-data.ts +81 -0
- package/tests/load-test/lead-to-domain.mapper.ts +24 -0
- package/tests/load-test/load.test.ts +38 -0
- package/tests/repository.test.ts +30 -54
- package/tests/to-json.test.ts +14 -18
- package/tests/utils.ts +138 -102
- package/tests/value-objects.test.ts +57 -29
- package/dist/deep-proxy.d.ts +0 -36
- package/dist/deep-proxy.d.ts.map +0 -1
- package/dist/deep-proxy.js +0 -384
- package/dist/deep-proxy.js.map +0 -1
- package/src/deep-proxy.ts +0 -447
- package/tests/entity.test.ts +0 -33
|
@@ -10,7 +10,7 @@ class Order extends Entity<{ id: Id; total: number; status: string }> {}
|
|
|
10
10
|
describe("Entity Equality by ID", () => {
|
|
11
11
|
describe("Basic Equality", () => {
|
|
12
12
|
it("should be equal when entities have the same ID", () => {
|
|
13
|
-
const id =
|
|
13
|
+
const id = Id.from("user-123");
|
|
14
14
|
const user1 = new User({
|
|
15
15
|
id,
|
|
16
16
|
name: "John",
|
|
@@ -18,10 +18,9 @@ describe("Entity Equality by ID", () => {
|
|
|
18
18
|
address: new Address({
|
|
19
19
|
street: "Main St",
|
|
20
20
|
city: "NYC",
|
|
21
|
-
zipCode: "10001",
|
|
22
21
|
}),
|
|
23
|
-
comments: [],
|
|
24
22
|
posts: [],
|
|
23
|
+
tags: [],
|
|
25
24
|
});
|
|
26
25
|
const user2 = new User({
|
|
27
26
|
id,
|
|
@@ -30,10 +29,9 @@ describe("Entity Equality by ID", () => {
|
|
|
30
29
|
address: new Address({
|
|
31
30
|
street: "Main St",
|
|
32
31
|
city: "NYC",
|
|
33
|
-
zipCode: "10001",
|
|
34
32
|
}),
|
|
35
|
-
comments: [],
|
|
36
33
|
posts: [],
|
|
34
|
+
tags: [],
|
|
37
35
|
});
|
|
38
36
|
|
|
39
37
|
expect(user1.equals(user2)).toBe(true);
|
|
@@ -49,9 +47,8 @@ describe("Entity Equality by ID", () => {
|
|
|
49
47
|
address: new Address({
|
|
50
48
|
street: "Main St",
|
|
51
49
|
city: "NYC",
|
|
52
|
-
zipCode: "10001",
|
|
53
50
|
}),
|
|
54
|
-
|
|
51
|
+
tags: [],
|
|
55
52
|
posts: [],
|
|
56
53
|
});
|
|
57
54
|
const user2 = new User({
|
|
@@ -61,9 +58,8 @@ describe("Entity Equality by ID", () => {
|
|
|
61
58
|
address: new Address({
|
|
62
59
|
street: "Main St",
|
|
63
60
|
city: "NYC",
|
|
64
|
-
zipCode: "10001",
|
|
65
61
|
}),
|
|
66
|
-
|
|
62
|
+
tags: [],
|
|
67
63
|
posts: [],
|
|
68
64
|
});
|
|
69
65
|
|
|
@@ -78,9 +74,8 @@ describe("Entity Equality by ID", () => {
|
|
|
78
74
|
address: new Address({
|
|
79
75
|
street: "Main St",
|
|
80
76
|
city: "NYC",
|
|
81
|
-
zipCode: "10001",
|
|
82
77
|
}),
|
|
83
|
-
|
|
78
|
+
tags: [],
|
|
84
79
|
posts: [],
|
|
85
80
|
});
|
|
86
81
|
const user2 = new User({
|
|
@@ -90,9 +85,8 @@ describe("Entity Equality by ID", () => {
|
|
|
90
85
|
address: new Address({
|
|
91
86
|
street: "Main St",
|
|
92
87
|
city: "NYC",
|
|
93
|
-
zipCode: "10001",
|
|
94
88
|
}),
|
|
95
|
-
|
|
89
|
+
tags: [],
|
|
96
90
|
posts: [],
|
|
97
91
|
});
|
|
98
92
|
|
|
@@ -108,12 +102,10 @@ describe("Entity Equality by ID", () => {
|
|
|
108
102
|
address: new Address({
|
|
109
103
|
street: "Main St",
|
|
110
104
|
city: "NYC",
|
|
111
|
-
zipCode: "10001",
|
|
112
105
|
}),
|
|
113
|
-
|
|
106
|
+
tags: [],
|
|
114
107
|
posts: [],
|
|
115
108
|
});
|
|
116
|
-
|
|
117
109
|
expect(user.equals(user)).toBe(true);
|
|
118
110
|
});
|
|
119
111
|
});
|
|
@@ -128,9 +120,8 @@ describe("Entity Equality by ID", () => {
|
|
|
128
120
|
address: new Address({
|
|
129
121
|
street: "Main St",
|
|
130
122
|
city: "NYC",
|
|
131
|
-
zipCode: "10001",
|
|
132
123
|
}),
|
|
133
|
-
|
|
124
|
+
tags: [],
|
|
134
125
|
posts: [],
|
|
135
126
|
});
|
|
136
127
|
|
|
@@ -146,9 +137,8 @@ describe("Entity Equality by ID", () => {
|
|
|
146
137
|
address: new Address({
|
|
147
138
|
street: "Main St",
|
|
148
139
|
city: "NYC",
|
|
149
|
-
zipCode: "10001",
|
|
150
140
|
}),
|
|
151
|
-
|
|
141
|
+
tags: [],
|
|
152
142
|
posts: [],
|
|
153
143
|
});
|
|
154
144
|
|
|
@@ -165,9 +155,8 @@ describe("Entity Equality by ID", () => {
|
|
|
165
155
|
address: new Address({
|
|
166
156
|
street: "Main St",
|
|
167
157
|
city: "NYC",
|
|
168
|
-
zipCode: "10001",
|
|
169
158
|
}),
|
|
170
|
-
|
|
159
|
+
tags: [],
|
|
171
160
|
posts: [],
|
|
172
161
|
});
|
|
173
162
|
|
|
@@ -182,9 +171,8 @@ describe("Entity Equality by ID", () => {
|
|
|
182
171
|
address: new Address({
|
|
183
172
|
street: "Main St",
|
|
184
173
|
city: "NYC",
|
|
185
|
-
zipCode: "10001",
|
|
186
174
|
}),
|
|
187
|
-
|
|
175
|
+
tags: [],
|
|
188
176
|
posts: [],
|
|
189
177
|
});
|
|
190
178
|
|
|
@@ -201,9 +189,8 @@ describe("Entity Equality by ID", () => {
|
|
|
201
189
|
address: new Address({
|
|
202
190
|
street: "Main St",
|
|
203
191
|
city: "NYC",
|
|
204
|
-
zipCode: "10001",
|
|
205
192
|
}),
|
|
206
|
-
|
|
193
|
+
tags: [],
|
|
207
194
|
posts: [],
|
|
208
195
|
});
|
|
209
196
|
|
|
@@ -218,9 +205,8 @@ describe("Entity Equality by ID", () => {
|
|
|
218
205
|
address: new Address({
|
|
219
206
|
street: "Main St",
|
|
220
207
|
city: "NYC",
|
|
221
|
-
zipCode: "10001",
|
|
222
208
|
}),
|
|
223
|
-
|
|
209
|
+
tags: [],
|
|
224
210
|
posts: [],
|
|
225
211
|
});
|
|
226
212
|
|
|
@@ -234,9 +220,8 @@ describe("Entity Equality by ID", () => {
|
|
|
234
220
|
address: new Address({
|
|
235
221
|
street: "Main St",
|
|
236
222
|
city: "NYC",
|
|
237
|
-
zipCode: "10001",
|
|
238
223
|
}),
|
|
239
|
-
|
|
224
|
+
tags: [],
|
|
240
225
|
posts: [],
|
|
241
226
|
});
|
|
242
227
|
const user2 = new User({
|
|
@@ -245,9 +230,8 @@ describe("Entity Equality by ID", () => {
|
|
|
245
230
|
address: new Address({
|
|
246
231
|
street: "Main St",
|
|
247
232
|
city: "NYC",
|
|
248
|
-
zipCode: "10001",
|
|
249
233
|
}),
|
|
250
|
-
|
|
234
|
+
tags: [],
|
|
251
235
|
posts: [],
|
|
252
236
|
});
|
|
253
237
|
|
|
@@ -269,9 +253,8 @@ describe("Entity Equality by ID", () => {
|
|
|
269
253
|
address: new Address({
|
|
270
254
|
street: "Main St",
|
|
271
255
|
city: "NYC",
|
|
272
|
-
zipCode: "10001",
|
|
273
256
|
}),
|
|
274
|
-
|
|
257
|
+
tags: [],
|
|
275
258
|
posts: [],
|
|
276
259
|
});
|
|
277
260
|
const order = new Order({ id, total: 100, status: "pending" });
|
|
@@ -291,9 +274,8 @@ describe("Entity Equality by ID", () => {
|
|
|
291
274
|
address: new Address({
|
|
292
275
|
street: "Main St",
|
|
293
276
|
city: "NYC",
|
|
294
|
-
zipCode: "10001",
|
|
295
277
|
}),
|
|
296
|
-
|
|
278
|
+
tags: [],
|
|
297
279
|
posts: [],
|
|
298
280
|
});
|
|
299
281
|
const user2 = new User({
|
|
@@ -303,18 +285,15 @@ describe("Entity Equality by ID", () => {
|
|
|
303
285
|
address: new Address({
|
|
304
286
|
street: "Main St",
|
|
305
287
|
city: "NYC",
|
|
306
|
-
zipCode: "10001",
|
|
307
288
|
}),
|
|
308
|
-
|
|
289
|
+
tags: [],
|
|
309
290
|
posts: [],
|
|
310
291
|
});
|
|
311
292
|
|
|
312
293
|
expect(user1.equals(user2)).toBe(true);
|
|
313
294
|
|
|
314
|
-
|
|
315
|
-
user1.name = "Johnny";
|
|
295
|
+
user1.changeName("Johnny");
|
|
316
296
|
|
|
317
|
-
// Still equal because ID is the same
|
|
318
297
|
expect(user1.equals(user2)).toBe(true);
|
|
319
298
|
});
|
|
320
299
|
});
|
|
@@ -329,9 +308,9 @@ describe("Entity Equality by ID", () => {
|
|
|
329
308
|
address: new Address({
|
|
330
309
|
street: "Main St",
|
|
331
310
|
city: "NYC",
|
|
332
|
-
zipCode: "10001",
|
|
333
311
|
}),
|
|
334
|
-
|
|
312
|
+
|
|
313
|
+
tags: [],
|
|
335
314
|
posts: [],
|
|
336
315
|
}),
|
|
337
316
|
new User({
|
|
@@ -341,9 +320,9 @@ describe("Entity Equality by ID", () => {
|
|
|
341
320
|
address: new Address({
|
|
342
321
|
street: "Main St",
|
|
343
322
|
city: "NYC",
|
|
344
|
-
zipCode: "10001",
|
|
345
323
|
}),
|
|
346
|
-
|
|
324
|
+
|
|
325
|
+
tags: [],
|
|
347
326
|
posts: [],
|
|
348
327
|
}),
|
|
349
328
|
new User({
|
|
@@ -353,9 +332,9 @@ describe("Entity Equality by ID", () => {
|
|
|
353
332
|
address: new Address({
|
|
354
333
|
street: "Main St",
|
|
355
334
|
city: "NYC",
|
|
356
|
-
zipCode: "10001",
|
|
357
335
|
}),
|
|
358
|
-
|
|
336
|
+
|
|
337
|
+
tags: [],
|
|
359
338
|
posts: [],
|
|
360
339
|
}),
|
|
361
340
|
];
|
|
@@ -376,9 +355,9 @@ describe("Entity Equality by ID", () => {
|
|
|
376
355
|
address: new Address({
|
|
377
356
|
street: "Main St",
|
|
378
357
|
city: "NYC",
|
|
379
|
-
zipCode: "10001",
|
|
380
358
|
}),
|
|
381
|
-
|
|
359
|
+
|
|
360
|
+
tags: [],
|
|
382
361
|
posts: [],
|
|
383
362
|
}),
|
|
384
363
|
new User({
|
|
@@ -388,9 +367,9 @@ describe("Entity Equality by ID", () => {
|
|
|
388
367
|
address: new Address({
|
|
389
368
|
street: "Main St",
|
|
390
369
|
city: "NYC",
|
|
391
|
-
zipCode: "10001",
|
|
392
370
|
}),
|
|
393
|
-
|
|
371
|
+
|
|
372
|
+
tags: [],
|
|
394
373
|
posts: [],
|
|
395
374
|
}),
|
|
396
375
|
new User({
|
|
@@ -400,9 +379,9 @@ describe("Entity Equality by ID", () => {
|
|
|
400
379
|
address: new Address({
|
|
401
380
|
street: "Main St",
|
|
402
381
|
city: "NYC",
|
|
403
|
-
zipCode: "10001",
|
|
404
382
|
}),
|
|
405
|
-
|
|
383
|
+
|
|
384
|
+
tags: [],
|
|
406
385
|
posts: [],
|
|
407
386
|
}),
|
|
408
387
|
];
|
|
@@ -424,9 +403,9 @@ describe("Entity Equality by ID", () => {
|
|
|
424
403
|
address: new Address({
|
|
425
404
|
street: "Main St",
|
|
426
405
|
city: "NYC",
|
|
427
|
-
zipCode: "10001",
|
|
428
406
|
}),
|
|
429
|
-
|
|
407
|
+
|
|
408
|
+
tags: [],
|
|
430
409
|
posts: [],
|
|
431
410
|
}),
|
|
432
411
|
new User({
|
|
@@ -436,9 +415,9 @@ describe("Entity Equality by ID", () => {
|
|
|
436
415
|
address: new Address({
|
|
437
416
|
street: "Main St",
|
|
438
417
|
city: "NYC",
|
|
439
|
-
zipCode: "10001",
|
|
440
418
|
}),
|
|
441
|
-
|
|
419
|
+
|
|
420
|
+
tags: [],
|
|
442
421
|
posts: [],
|
|
443
422
|
}),
|
|
444
423
|
];
|
|
@@ -450,9 +429,8 @@ describe("Entity Equality by ID", () => {
|
|
|
450
429
|
address: new Address({
|
|
451
430
|
street: "Main St",
|
|
452
431
|
city: "NYC",
|
|
453
|
-
zipCode: "10001",
|
|
454
432
|
}),
|
|
455
|
-
|
|
433
|
+
tags: [],
|
|
456
434
|
posts: [],
|
|
457
435
|
});
|
|
458
436
|
const user3 = new User({
|
|
@@ -462,9 +440,8 @@ describe("Entity Equality by ID", () => {
|
|
|
462
440
|
address: new Address({
|
|
463
441
|
street: "Main St",
|
|
464
442
|
city: "NYC",
|
|
465
|
-
zipCode: "10001",
|
|
466
443
|
}),
|
|
467
|
-
|
|
444
|
+
tags: [],
|
|
468
445
|
posts: [],
|
|
469
446
|
});
|
|
470
447
|
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tests: EntitySchemaRegistry
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { EntitySchemaRegistry } from "../src/entity-schema-registry";
|
|
6
|
+
|
|
7
|
+
describe("EntitySchemaRegistry", () => {
|
|
8
|
+
let registry: EntitySchemaRegistry;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
registry = new EntitySchemaRegistry();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("register", () => {
|
|
15
|
+
it("should register a schema", () => {
|
|
16
|
+
registry.register({
|
|
17
|
+
entity: "User",
|
|
18
|
+
table: "users",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
expect(registry.has("User")).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should allow chaining", () => {
|
|
25
|
+
const result = registry
|
|
26
|
+
.register({ entity: "User", table: "users" })
|
|
27
|
+
.register({ entity: "Post", table: "posts" });
|
|
28
|
+
|
|
29
|
+
expect(result).toBe(registry);
|
|
30
|
+
expect(registry.has("User")).toBe(true);
|
|
31
|
+
expect(registry.has("Post")).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should register with fields mapping", () => {
|
|
35
|
+
registry.register({
|
|
36
|
+
entity: "User",
|
|
37
|
+
table: "users",
|
|
38
|
+
fields: {
|
|
39
|
+
email: "user_email",
|
|
40
|
+
name: "user_name",
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(registry.getFieldsMap("User")).toEqual({
|
|
45
|
+
email: "user_email",
|
|
46
|
+
name: "user_name",
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should register with parent FK", () => {
|
|
51
|
+
registry.register({
|
|
52
|
+
entity: "Post",
|
|
53
|
+
table: "posts",
|
|
54
|
+
parentFk: {
|
|
55
|
+
field: "author_id",
|
|
56
|
+
parentEntity: "User",
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(registry.getParentEntity("Post")).toBe("User");
|
|
61
|
+
expect(registry.getParentFkField("Post")).toBe("author_id");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("registerAll", () => {
|
|
66
|
+
it("should register multiple schemas at once", () => {
|
|
67
|
+
registry.registerAll([
|
|
68
|
+
{ entity: "User", table: "users" },
|
|
69
|
+
{ entity: "Post", table: "posts" },
|
|
70
|
+
{ entity: "Comment", table: "comments" },
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
expect(registry.getRegisteredEntities()).toEqual([
|
|
74
|
+
"User",
|
|
75
|
+
"Post",
|
|
76
|
+
"Comment",
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("getSchema", () => {
|
|
82
|
+
it("should return registered schema", () => {
|
|
83
|
+
registry.register({
|
|
84
|
+
entity: "User",
|
|
85
|
+
table: "users",
|
|
86
|
+
fields: { email: "user_email" },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const schema = registry.getSchema("User");
|
|
90
|
+
|
|
91
|
+
expect(schema.entity).toBe("User");
|
|
92
|
+
expect(schema.table).toBe("users");
|
|
93
|
+
expect(schema.fields).toEqual({ email: "user_email" });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("should throw for unregistered entity", () => {
|
|
97
|
+
expect(() => registry.getSchema("Unknown")).toThrow(
|
|
98
|
+
"No schema registered for entity 'Unknown'"
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe("getTable", () => {
|
|
104
|
+
it("should return table name", () => {
|
|
105
|
+
registry.register({ entity: "User", table: "app_users" });
|
|
106
|
+
|
|
107
|
+
expect(registry.getTable("User")).toBe("app_users");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("mapFieldName", () => {
|
|
112
|
+
beforeEach(() => {
|
|
113
|
+
registry.register({
|
|
114
|
+
entity: "User",
|
|
115
|
+
table: "users",
|
|
116
|
+
fields: {
|
|
117
|
+
email: "user_email",
|
|
118
|
+
createdAt: "created_at",
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should map field with different name", () => {
|
|
124
|
+
expect(registry.mapFieldName("User", "email")).toBe("user_email");
|
|
125
|
+
expect(registry.mapFieldName("User", "createdAt")).toBe("created_at");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("should return original name if not mapped", () => {
|
|
129
|
+
expect(registry.mapFieldName("User", "name")).toBe("name");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("mapFields", () => {
|
|
134
|
+
beforeEach(() => {
|
|
135
|
+
registry.register({
|
|
136
|
+
entity: "User",
|
|
137
|
+
table: "users",
|
|
138
|
+
fields: {
|
|
139
|
+
email: "user_email",
|
|
140
|
+
name: "user_name",
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should map all fields", () => {
|
|
146
|
+
const data = {
|
|
147
|
+
email: "test@test.com",
|
|
148
|
+
name: "Test User",
|
|
149
|
+
age: 25,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const mapped = registry.mapFields("User", data);
|
|
153
|
+
|
|
154
|
+
expect(mapped).toEqual({
|
|
155
|
+
user_email: "test@test.com",
|
|
156
|
+
user_name: "Test User",
|
|
157
|
+
age: 25,
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should ignore arrays", () => {
|
|
162
|
+
const data = {
|
|
163
|
+
email: "test@test.com",
|
|
164
|
+
posts: [{ id: "1" }, { id: "2" }],
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const mapped = registry.mapFields("User", data);
|
|
168
|
+
|
|
169
|
+
expect(mapped).toEqual({ user_email: "test@test.com" });
|
|
170
|
+
expect(mapped.posts).toBeUndefined();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("should handle null and undefined values", () => {
|
|
174
|
+
const data = {
|
|
175
|
+
email: null,
|
|
176
|
+
name: undefined,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const mapped = registry.mapFields("User", data);
|
|
180
|
+
|
|
181
|
+
expect(mapped.user_email).toBeNull();
|
|
182
|
+
expect(mapped.user_name).toBeUndefined();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("mapEntity", () => {
|
|
187
|
+
beforeEach(() => {
|
|
188
|
+
registry.register({
|
|
189
|
+
entity: "User",
|
|
190
|
+
table: "users",
|
|
191
|
+
fields: {
|
|
192
|
+
email: "user_email",
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("should map entity with ID", () => {
|
|
198
|
+
// Mock Entity
|
|
199
|
+
const mockEntity = {
|
|
200
|
+
id: { value: "user-123" },
|
|
201
|
+
props: {
|
|
202
|
+
email: "test@test.com",
|
|
203
|
+
name: "Test",
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const mapped = registry.mapEntity("User", mockEntity as any);
|
|
208
|
+
|
|
209
|
+
expect(mapped).toEqual({
|
|
210
|
+
id: "user-123",
|
|
211
|
+
user_email: "test@test.com",
|
|
212
|
+
name: "Test",
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should skip nested entities and arrays", () => {
|
|
217
|
+
const mockEntity = {
|
|
218
|
+
id: { value: "user-123" },
|
|
219
|
+
props: {
|
|
220
|
+
email: "test@test.com",
|
|
221
|
+
posts: [],
|
|
222
|
+
address: { id: { value: "addr-1" } },
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const mapped = registry.mapEntity("User", mockEntity as any);
|
|
227
|
+
|
|
228
|
+
expect(mapped.id).toBe("user-123");
|
|
229
|
+
expect(mapped.user_email).toBe("test@test.com");
|
|
230
|
+
expect(mapped.posts).toBeUndefined();
|
|
231
|
+
expect(mapped.address).toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe("getParentFk", () => {
|
|
236
|
+
beforeEach(() => {
|
|
237
|
+
registry.register({
|
|
238
|
+
entity: "Post",
|
|
239
|
+
table: "posts",
|
|
240
|
+
parentFk: {
|
|
241
|
+
field: "author_id",
|
|
242
|
+
parentEntity: "User",
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
registry.register({
|
|
246
|
+
entity: "User",
|
|
247
|
+
table: "users",
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("should return FK object", () => {
|
|
252
|
+
const fk = registry.getParentFk("Post", "user-123");
|
|
253
|
+
|
|
254
|
+
expect(fk).toEqual({ author_id: "user-123" });
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should return null if no parent FK defined", () => {
|
|
258
|
+
const fk = registry.getParentFk("User", "user-123");
|
|
259
|
+
|
|
260
|
+
expect(fk).toBeNull();
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
describe("getParentEntity", () => {
|
|
265
|
+
it("should return parent entity name", () => {
|
|
266
|
+
registry.register({
|
|
267
|
+
entity: "Post",
|
|
268
|
+
table: "posts",
|
|
269
|
+
parentFk: { field: "author_id", parentEntity: "User" },
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(registry.getParentEntity("Post")).toBe("User");
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("should return null if no parent", () => {
|
|
276
|
+
registry.register({ entity: "User", table: "users" });
|
|
277
|
+
|
|
278
|
+
expect(registry.getParentEntity("User")).toBeNull();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe("getRegisteredEntities", () => {
|
|
283
|
+
it("should return all registered entity names", () => {
|
|
284
|
+
registry
|
|
285
|
+
.register({ entity: "User", table: "users" })
|
|
286
|
+
.register({ entity: "Post", table: "posts" })
|
|
287
|
+
.register({ entity: "Comment", table: "comments" });
|
|
288
|
+
|
|
289
|
+
expect(registry.getRegisteredEntities()).toEqual([
|
|
290
|
+
"User",
|
|
291
|
+
"Post",
|
|
292
|
+
"Comment",
|
|
293
|
+
]);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it("should return empty array if none registered", () => {
|
|
297
|
+
expect(registry.getRegisteredEntities()).toEqual([]);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe("clear", () => {
|
|
302
|
+
it("should remove all schemas", () => {
|
|
303
|
+
registry
|
|
304
|
+
.register({ entity: "User", table: "users" })
|
|
305
|
+
.register({ entity: "Post", table: "posts" });
|
|
306
|
+
|
|
307
|
+
registry.clear();
|
|
308
|
+
|
|
309
|
+
expect(registry.getRegisteredEntities()).toEqual([]);
|
|
310
|
+
expect(registry.has("User")).toBe(false);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
describe("complex scenario", () => {
|
|
315
|
+
beforeEach(() => {
|
|
316
|
+
registry
|
|
317
|
+
.register({
|
|
318
|
+
entity: "User",
|
|
319
|
+
table: "users",
|
|
320
|
+
fields: {
|
|
321
|
+
email: "user_email",
|
|
322
|
+
name: "user_name",
|
|
323
|
+
},
|
|
324
|
+
})
|
|
325
|
+
.register({
|
|
326
|
+
entity: "Post",
|
|
327
|
+
table: "blog_posts",
|
|
328
|
+
fields: {
|
|
329
|
+
content: "post_content",
|
|
330
|
+
},
|
|
331
|
+
parentFk: { field: "author_id", parentEntity: "User" },
|
|
332
|
+
})
|
|
333
|
+
.register({
|
|
334
|
+
entity: "Comment",
|
|
335
|
+
table: "post_comments",
|
|
336
|
+
fields: {
|
|
337
|
+
text: "comment_text",
|
|
338
|
+
},
|
|
339
|
+
parentFk: { field: "post_id", parentEntity: "Post" },
|
|
340
|
+
})
|
|
341
|
+
.register({
|
|
342
|
+
entity: "Like",
|
|
343
|
+
table: "comment_likes",
|
|
344
|
+
fields: {
|
|
345
|
+
userId: "user_id",
|
|
346
|
+
},
|
|
347
|
+
parentFk: { field: "comment_id", parentEntity: "Comment" },
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it("should handle full hierarchy", () => {
|
|
352
|
+
expect(registry.getTable("User")).toBe("users");
|
|
353
|
+
expect(registry.getTable("Post")).toBe("blog_posts");
|
|
354
|
+
expect(registry.getTable("Comment")).toBe("post_comments");
|
|
355
|
+
expect(registry.getTable("Like")).toBe("comment_likes");
|
|
356
|
+
|
|
357
|
+
expect(registry.getParentEntity("Post")).toBe("User");
|
|
358
|
+
expect(registry.getParentEntity("Comment")).toBe("Post");
|
|
359
|
+
expect(registry.getParentEntity("Like")).toBe("Comment");
|
|
360
|
+
expect(registry.getParentEntity("User")).toBeNull();
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("should map fields correctly for each entity", () => {
|
|
364
|
+
expect(registry.mapFieldName("User", "email")).toBe("user_email");
|
|
365
|
+
expect(registry.mapFieldName("Post", "content")).toBe("post_content");
|
|
366
|
+
expect(registry.mapFieldName("Comment", "text")).toBe("comment_text");
|
|
367
|
+
expect(registry.mapFieldName("Like", "userId")).toBe("user_id");
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it("should build FK chain", () => {
|
|
371
|
+
expect(registry.getParentFk("Post", "user-1")).toEqual({
|
|
372
|
+
author_id: "user-1",
|
|
373
|
+
});
|
|
374
|
+
expect(registry.getParentFk("Comment", "post-1")).toEqual({
|
|
375
|
+
post_id: "post-1",
|
|
376
|
+
});
|
|
377
|
+
expect(registry.getParentFk("Like", "comment-1")).toEqual({
|
|
378
|
+
comment_id: "comment-1",
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
});
|