@woltz/rich-domain 0.2.1 → 1.0.0
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 +42 -0
- package/README.md +37 -20
- package/dist/base-entity.d.ts +1 -1
- package/dist/base-entity.d.ts.map +1 -1
- package/dist/base-entity.js +21 -15
- package/dist/base-entity.js.map +1 -1
- package/dist/constants.js +4 -1
- package/dist/constants.js.map +1 -1
- package/dist/criteria.d.ts.map +1 -1
- package/dist/criteria.js +7 -3
- package/dist/criteria.js.map +1 -1
- package/dist/deep-proxy.d.ts +3 -1
- package/dist/deep-proxy.d.ts.map +1 -1
- package/dist/deep-proxy.js +110 -33
- package/dist/deep-proxy.js.map +1 -1
- package/dist/domain-event-bus.js +7 -2
- package/dist/domain-event-bus.js.map +1 -1
- package/dist/domain-event.js +7 -3
- package/dist/domain-event.js.map +1 -1
- package/dist/entity.js +8 -3
- package/dist/entity.js.map +1 -1
- package/dist/id.d.ts +3 -3
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +10 -6
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -16
- package/dist/index.js.map +1 -1
- package/dist/mapper.d.ts +4 -0
- package/dist/mapper.d.ts.map +1 -0
- package/dist/mapper.js +7 -0
- package/dist/mapper.js.map +1 -0
- package/dist/paginated-result.d.ts.map +1 -1
- package/dist/paginated-result.js +7 -6
- package/dist/paginated-result.js.map +1 -1
- package/dist/repository/base-repository.d.ts +25 -48
- package/dist/repository/base-repository.d.ts.map +1 -1
- package/dist/repository/base-repository.js +14 -51
- package/dist/repository/base-repository.js.map +1 -1
- package/dist/repository/in-memory-repository.d.ts +12 -8
- package/dist/repository/in-memory-repository.d.ts.map +1 -1
- package/dist/repository/in-memory-repository.js +24 -12
- package/dist/repository/in-memory-repository.js.map +1 -1
- package/dist/repository/index.d.ts +2 -39
- package/dist/repository/index.d.ts.map +1 -1
- package/dist/repository/index.js +26 -40
- package/dist/repository/index.js.map +1 -1
- package/dist/repository/unit-of-work.js +9 -3
- package/dist/repository/unit-of-work.js.map +1 -1
- package/dist/types/criteria.d.ts +2 -2
- package/dist/types/criteria.d.ts.map +1 -1
- package/dist/types/criteria.js +4 -1
- package/dist/types/criteria.js.map +1 -1
- package/dist/types/domain.js +2 -1
- package/dist/types/history-tracker.js +2 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +22 -7
- package/dist/types/index.js.map +1 -1
- package/dist/types/standard-schema.js +2 -1
- package/dist/types/unit-of-work.d.ts +2 -2
- package/dist/types/unit-of-work.d.ts.map +1 -1
- package/dist/types/unit-of-work.js +2 -1
- package/dist/types/utils.js +2 -1
- package/dist/validation-error.js +9 -3
- package/dist/validation-error.js.map +1 -1
- package/dist/value-object.js +9 -5
- package/dist/value-object.js.map +1 -1
- package/package.json +1 -1
- package/src/base-entity.ts +3 -2
- package/src/criteria.ts +2 -2
- package/src/deep-proxy.ts +435 -339
- package/src/id.ts +4 -4
- package/src/index.ts +2 -3
- package/src/mapper.ts +3 -0
- package/src/paginated-result.ts +1 -8
- package/src/repository/base-repository.ts +27 -115
- package/src/repository/in-memory-repository.ts +28 -16
- package/src/repository/index.ts +2 -40
- package/src/types/criteria.ts +2 -2
- package/src/types/index.ts +0 -1
- package/src/types/unit-of-work.ts +3 -3
- package/tests/entity-validation.test.ts +1 -1
- package/tests/history-tracker.spec.ts +57 -17
- package/tests/id.test.ts +341 -341
- package/tests/repository.test.ts +95 -79
- package/tests/to-json.test.ts +103 -91
- package/tests/value-objects.test.ts +52 -52
- package/tsconfig.json +2 -2
- package/dist/filtering.d.ts +0 -107
- package/dist/filtering.d.ts.map +0 -1
- package/dist/filtering.js +0 -202
- package/dist/filtering.js.map +0 -1
- package/dist/ordering.d.ts +0 -93
- package/dist/ordering.d.ts.map +0 -1
- package/dist/ordering.js +0 -154
- package/dist/ordering.js.map +0 -1
- package/dist/pagination.d.ts +0 -218
- package/dist/pagination.d.ts.map +0 -1
- package/dist/pagination.js +0 -281
- package/dist/pagination.js.map +0 -1
- package/dist/repository/mapper.d.ts +0 -56
- package/dist/repository/mapper.d.ts.map +0 -1
- package/dist/repository/mapper.js +0 -15
- package/dist/repository/mapper.js.map +0 -1
- package/dist/repository/types.d.ts +0 -87
- package/dist/repository/types.d.ts.map +0 -1
- package/dist/repository/types.js +0 -6
- package/dist/repository/types.js.map +0 -1
- package/dist/repository.d.ts +0 -2
- package/dist/repository.d.ts.map +0 -1
- package/dist/repository.js +0 -21
- package/dist/repository.js.map +0 -1
- package/dist/specification.d.ts +0 -102
- package/dist/specification.d.ts.map +0 -1
- package/dist/specification.js +0 -187
- package/dist/specification.js.map +0 -1
- package/dist/types/repository.d.ts +0 -43
- package/dist/types/repository.d.ts.map +0 -1
- package/dist/types/repository.js +0 -2
- package/dist/types/repository.js.map +0 -1
- package/dist/types.d.ts +0 -88
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +0 -1
- package/src/repository/mapper.ts +0 -74
- package/src/types/repository.ts +0 -51
package/tests/repository.test.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { Id, Aggregate, Criteria, BaseProps, PaginatedResult } from "../src";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
BaseRepository,
|
|
5
|
-
BaseMapper,
|
|
6
|
-
} from "../src/repository";
|
|
2
|
+
import { InMemoryRepository, Mapper } from "../src/repository";
|
|
3
|
+
import { Repository } from "../src/repository/base-repository";
|
|
7
4
|
|
|
8
5
|
// ============================================================================
|
|
9
6
|
// Test Domain Models
|
|
@@ -73,9 +70,8 @@ type UserPersistence = {
|
|
|
73
70
|
// ============================================================================
|
|
74
71
|
// Mapper Implementation
|
|
75
72
|
// ============================================================================
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
toDomain(persistence: UserPersistence): User {
|
|
73
|
+
class UserToDomainMapper extends Mapper<UserPersistence, User> {
|
|
74
|
+
public build(persistence: UserPersistence): User {
|
|
79
75
|
return User.create({
|
|
80
76
|
id: Id.from(persistence.id),
|
|
81
77
|
name: persistence.name,
|
|
@@ -84,8 +80,10 @@ class UserMapper extends BaseMapper<User, UserPersistence> {
|
|
|
84
80
|
status: persistence.status as "active" | "inactive",
|
|
85
81
|
});
|
|
86
82
|
}
|
|
83
|
+
}
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
class UserToPersistenceMapper extends Mapper<User, UserPersistence> {
|
|
86
|
+
public build(domain: User): UserPersistence {
|
|
89
87
|
return {
|
|
90
88
|
id: domain.id.value,
|
|
91
89
|
name: domain.name,
|
|
@@ -102,41 +100,51 @@ class UserMapper extends BaseMapper<User, UserPersistence> {
|
|
|
102
100
|
// Mock Repository Implementation
|
|
103
101
|
// ============================================================================
|
|
104
102
|
|
|
105
|
-
class MockUserRepository extends
|
|
103
|
+
class MockUserRepository extends Repository<User> {
|
|
106
104
|
private store: Map<string, UserPersistence> = new Map();
|
|
107
105
|
|
|
108
|
-
constructor(
|
|
109
|
-
|
|
106
|
+
constructor(
|
|
107
|
+
protected readonly mapperToDomain: Mapper<UserPersistence, User>,
|
|
108
|
+
protected readonly mapperToPersistence: Mapper<User, UserPersistence>
|
|
109
|
+
) {
|
|
110
|
+
super();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get model() {
|
|
114
|
+
return "users";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async create(entity: User) {
|
|
118
|
+
const persistence = this.mapperToPersistence.build(entity);
|
|
119
|
+
this.store.set(entity.id.value, persistence);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async delete(entity: User): Promise<void> {
|
|
123
|
+
this.store.delete(entity.id.value);
|
|
110
124
|
}
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
this.
|
|
114
|
-
return data;
|
|
126
|
+
async count(criteria: Criteria<User>): Promise<number> {
|
|
127
|
+
return this.applyCriteria(criteria).then((result) => result.meta.total);
|
|
115
128
|
}
|
|
116
129
|
|
|
117
|
-
|
|
118
|
-
id
|
|
119
|
-
data: UserPersistence
|
|
120
|
-
): Promise<UserPersistence> {
|
|
121
|
-
this.store.set(id, { ...data, updatedAt: new Date() });
|
|
122
|
-
return data;
|
|
130
|
+
async exists(id: string): Promise<boolean> {
|
|
131
|
+
return this.store.has(id);
|
|
123
132
|
}
|
|
124
133
|
|
|
125
|
-
|
|
126
|
-
this.
|
|
134
|
+
async find(criteria: Criteria<User>): Promise<PaginatedResult<User>> {
|
|
135
|
+
const result = await this.applyCriteria(criteria);
|
|
136
|
+
return result;
|
|
127
137
|
}
|
|
128
138
|
|
|
129
|
-
|
|
139
|
+
async findById(id: string): Promise<User | null> {
|
|
130
140
|
const persistence = this.store.get(id);
|
|
131
141
|
if (!persistence) return null;
|
|
132
|
-
return this.
|
|
142
|
+
return this.mapperToDomain.build(persistence);
|
|
133
143
|
}
|
|
134
144
|
|
|
135
|
-
|
|
136
|
-
const persistence =
|
|
137
|
-
|
|
138
|
-
? this.mapper.toDomainList(persistence)
|
|
139
|
-
: persistence.map((p) => this.mapper.toDomain(p));
|
|
145
|
+
async update(entity: User): Promise<void> {
|
|
146
|
+
const persistence = this.mapperToPersistence.build(entity);
|
|
147
|
+
this.store.set(entity.id.value, persistence);
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
protected async applyCriteria(criteria: Criteria<User>) {
|
|
@@ -183,9 +191,7 @@ class MockUserRepository extends BaseRepository<User, UserPersistence> {
|
|
|
183
191
|
pagination.offset + pagination.limit
|
|
184
192
|
);
|
|
185
193
|
|
|
186
|
-
const domains = this.
|
|
187
|
-
? this.mapper.toDomainList(results)
|
|
188
|
-
: results.map((p) => this.mapper.toDomain(p));
|
|
194
|
+
const domains = results.map((p) => this.mapperToDomain.build(p));
|
|
189
195
|
|
|
190
196
|
return PaginatedResult.create(domains, pagination, total);
|
|
191
197
|
}
|
|
@@ -221,7 +227,10 @@ describe("Repository", () => {
|
|
|
221
227
|
let user3: User;
|
|
222
228
|
|
|
223
229
|
beforeEach(() => {
|
|
224
|
-
repository = new InMemoryRepository<User>(
|
|
230
|
+
repository = new InMemoryRepository<User>(
|
|
231
|
+
new UserToDomainMapper(),
|
|
232
|
+
new UserToPersistenceMapper()
|
|
233
|
+
);
|
|
225
234
|
|
|
226
235
|
user1 = User.create({
|
|
227
236
|
name: "Alice",
|
|
@@ -251,8 +260,8 @@ describe("Repository", () => {
|
|
|
251
260
|
|
|
252
261
|
describe("save and findById", () => {
|
|
253
262
|
it("should save and retrieve user", async () => {
|
|
254
|
-
await repository.
|
|
255
|
-
const found = await repository.findById(user1.id);
|
|
263
|
+
await repository.create(user1);
|
|
264
|
+
const found = await repository.findById(user1.id.value);
|
|
256
265
|
|
|
257
266
|
expect(found).toBeDefined();
|
|
258
267
|
expect(found?.id.equals(user1.id)).toBe(true);
|
|
@@ -260,16 +269,16 @@ describe("Repository", () => {
|
|
|
260
269
|
});
|
|
261
270
|
|
|
262
271
|
it("should return null for non-existent id", async () => {
|
|
263
|
-
const found = await repository.findById(new Id());
|
|
272
|
+
const found = await repository.findById(new Id().value);
|
|
264
273
|
expect(found).toBeNull();
|
|
265
274
|
});
|
|
266
275
|
|
|
267
276
|
it("should update existing user", async () => {
|
|
268
|
-
await repository.
|
|
277
|
+
await repository.create(user1);
|
|
269
278
|
user1.setName("Alice Updated");
|
|
270
|
-
await repository.
|
|
279
|
+
await repository.create(user1);
|
|
271
280
|
|
|
272
|
-
const found = await repository.findById(user1.id);
|
|
281
|
+
const found = await repository.findById(user1.id.value);
|
|
273
282
|
expect(found?.name).toBe("Alice Updated");
|
|
274
283
|
});
|
|
275
284
|
});
|
|
@@ -281,18 +290,18 @@ describe("Repository", () => {
|
|
|
281
290
|
});
|
|
282
291
|
|
|
283
292
|
it("should return all users", async () => {
|
|
284
|
-
await repository.
|
|
285
|
-
await repository.
|
|
286
|
-
await repository.
|
|
293
|
+
await repository.create(user1);
|
|
294
|
+
await repository.create(user2);
|
|
295
|
+
await repository.create(user3);
|
|
287
296
|
|
|
288
297
|
const users = await repository.findAll();
|
|
289
298
|
expect(users).toHaveLength(3);
|
|
290
299
|
});
|
|
291
300
|
|
|
292
301
|
it("should return users matching criteria", async () => {
|
|
293
|
-
await repository.
|
|
294
|
-
await repository.
|
|
295
|
-
await repository.
|
|
302
|
+
await repository.create(user1);
|
|
303
|
+
await repository.create(user2);
|
|
304
|
+
await repository.create(user3);
|
|
296
305
|
|
|
297
306
|
const criteria = Criteria.create<User>().whereEquals(
|
|
298
307
|
"status",
|
|
@@ -307,9 +316,9 @@ describe("Repository", () => {
|
|
|
307
316
|
|
|
308
317
|
describe("find with Criteria", () => {
|
|
309
318
|
beforeEach(async () => {
|
|
310
|
-
await repository.
|
|
311
|
-
await repository.
|
|
312
|
-
await repository.
|
|
319
|
+
await repository.create(user1);
|
|
320
|
+
await repository.create(user2);
|
|
321
|
+
await repository.create(user3);
|
|
313
322
|
});
|
|
314
323
|
|
|
315
324
|
it("should filter by equals", async () => {
|
|
@@ -364,8 +373,8 @@ describe("Repository", () => {
|
|
|
364
373
|
|
|
365
374
|
describe("findOne", () => {
|
|
366
375
|
it("should find first matching user", async () => {
|
|
367
|
-
await repository.
|
|
368
|
-
await repository.
|
|
376
|
+
await repository.create(user1);
|
|
377
|
+
await repository.create(user2);
|
|
369
378
|
|
|
370
379
|
const criteria = Criteria.create<User>().whereEquals(
|
|
371
380
|
"status",
|
|
@@ -390,40 +399,40 @@ describe("Repository", () => {
|
|
|
390
399
|
|
|
391
400
|
describe("delete", () => {
|
|
392
401
|
it("should delete by aggregate", async () => {
|
|
393
|
-
await repository.
|
|
402
|
+
await repository.create(user1);
|
|
394
403
|
await repository.delete(user1);
|
|
395
404
|
|
|
396
|
-
const found = await repository.findById(user1.id);
|
|
405
|
+
const found = await repository.findById(user1.id.value);
|
|
397
406
|
expect(found).toBeNull();
|
|
398
407
|
});
|
|
399
408
|
|
|
400
409
|
it("should delete by id", async () => {
|
|
401
|
-
await repository.
|
|
402
|
-
await repository.
|
|
410
|
+
await repository.create(user1);
|
|
411
|
+
await repository.delete(user1);
|
|
403
412
|
|
|
404
|
-
const found = await repository.findById(user1.id);
|
|
413
|
+
const found = await repository.findById(user1.id.value);
|
|
405
414
|
expect(found).toBeNull();
|
|
406
415
|
});
|
|
407
416
|
});
|
|
408
417
|
|
|
409
418
|
describe("exists", () => {
|
|
410
419
|
it("should return true when user exists", async () => {
|
|
411
|
-
await repository.
|
|
412
|
-
const exists = await repository.exists(user1.id);
|
|
420
|
+
await repository.create(user1);
|
|
421
|
+
const exists = await repository.exists(user1.id.value);
|
|
413
422
|
expect(exists).toBe(true);
|
|
414
423
|
});
|
|
415
424
|
|
|
416
425
|
it("should return false when user does not exist", async () => {
|
|
417
|
-
const exists = await repository.exists(new Id());
|
|
426
|
+
const exists = await repository.exists(new Id().value);
|
|
418
427
|
expect(exists).toBe(false);
|
|
419
428
|
});
|
|
420
429
|
});
|
|
421
430
|
|
|
422
431
|
describe("count", () => {
|
|
423
432
|
beforeEach(async () => {
|
|
424
|
-
await repository.
|
|
425
|
-
await repository.
|
|
426
|
-
await repository.
|
|
433
|
+
await repository.create(user1);
|
|
434
|
+
await repository.create(user2);
|
|
435
|
+
await repository.create(user3);
|
|
427
436
|
});
|
|
428
437
|
|
|
429
438
|
it("should count all users", async () => {
|
|
@@ -443,7 +452,7 @@ describe("Repository", () => {
|
|
|
443
452
|
|
|
444
453
|
describe("saveMany", () => {
|
|
445
454
|
it("should save multiple users", async () => {
|
|
446
|
-
await repository.
|
|
455
|
+
await repository.createMany([user1, user2, user3]);
|
|
447
456
|
|
|
448
457
|
const users = await repository.findAll();
|
|
449
458
|
expect(users).toHaveLength(3);
|
|
@@ -456,7 +465,10 @@ describe("Repository", () => {
|
|
|
456
465
|
let user: User;
|
|
457
466
|
|
|
458
467
|
beforeEach(() => {
|
|
459
|
-
repository = new MockUserRepository(
|
|
468
|
+
repository = new MockUserRepository(
|
|
469
|
+
new UserToDomainMapper(),
|
|
470
|
+
new UserToPersistenceMapper()
|
|
471
|
+
);
|
|
460
472
|
user = User.create({
|
|
461
473
|
name: "John",
|
|
462
474
|
email: "john@example.com",
|
|
@@ -470,16 +482,16 @@ describe("Repository", () => {
|
|
|
470
482
|
});
|
|
471
483
|
|
|
472
484
|
it("should save new user (insert)", async () => {
|
|
473
|
-
expect(user.isNew).toBe(true);
|
|
474
|
-
await repository.
|
|
485
|
+
expect(user.isNew()).toBe(true);
|
|
486
|
+
await repository.create(user);
|
|
475
487
|
|
|
476
|
-
const found = await repository.findById(user.id);
|
|
488
|
+
const found = await repository.findById(user.id.value);
|
|
477
489
|
expect(found).toBeDefined();
|
|
478
490
|
expect(found?.name).toBe("John");
|
|
479
491
|
});
|
|
480
492
|
|
|
481
493
|
it("should update existing user", async () => {
|
|
482
|
-
await repository.
|
|
494
|
+
await repository.create(user);
|
|
483
495
|
|
|
484
496
|
// Simulate existing user
|
|
485
497
|
const existingUser = User.create({
|
|
@@ -490,16 +502,16 @@ describe("Repository", () => {
|
|
|
490
502
|
status: "inactive",
|
|
491
503
|
});
|
|
492
504
|
|
|
493
|
-
await repository.
|
|
505
|
+
await repository.create(existingUser);
|
|
494
506
|
|
|
495
|
-
const found = await repository.findById(user.id);
|
|
507
|
+
const found = await repository.findById(user.id.value);
|
|
496
508
|
expect(found?.name).toBe("John Updated");
|
|
497
509
|
expect(found?.age).toBe(29);
|
|
498
510
|
});
|
|
499
511
|
|
|
500
512
|
it("should convert between domain and persistence", async () => {
|
|
501
|
-
await repository.
|
|
502
|
-
const found = await repository.findById(user.id);
|
|
513
|
+
await repository.create(user);
|
|
514
|
+
const found = await repository.findById(user.id.value);
|
|
503
515
|
|
|
504
516
|
// Should be a domain object
|
|
505
517
|
expect(found).toBeInstanceOf(User);
|
|
@@ -520,7 +532,7 @@ describe("Repository", () => {
|
|
|
520
532
|
status: "inactive",
|
|
521
533
|
});
|
|
522
534
|
|
|
523
|
-
await Promise.all([repository.
|
|
535
|
+
await Promise.all([repository.create(user1), repository.create(user2)]);
|
|
524
536
|
|
|
525
537
|
const result = await repository.find(
|
|
526
538
|
Criteria.create<User>()
|
|
@@ -535,10 +547,12 @@ describe("Repository", () => {
|
|
|
535
547
|
});
|
|
536
548
|
|
|
537
549
|
describe("Mapper", () => {
|
|
538
|
-
let
|
|
550
|
+
let toDomainMapper: UserToDomainMapper;
|
|
551
|
+
let toPersistenceMapper: UserToPersistenceMapper;
|
|
539
552
|
|
|
540
553
|
beforeEach(() => {
|
|
541
|
-
|
|
554
|
+
toDomainMapper = new UserToDomainMapper();
|
|
555
|
+
toPersistenceMapper = new UserToPersistenceMapper();
|
|
542
556
|
});
|
|
543
557
|
|
|
544
558
|
it("should convert from persistence to domain", () => {
|
|
@@ -552,7 +566,7 @@ describe("Repository", () => {
|
|
|
552
566
|
updatedAt: new Date(),
|
|
553
567
|
};
|
|
554
568
|
|
|
555
|
-
const domain =
|
|
569
|
+
const domain = toDomainMapper.build(persistence);
|
|
556
570
|
|
|
557
571
|
expect(domain).toBeInstanceOf(User);
|
|
558
572
|
expect(domain.id.value).toBe("123");
|
|
@@ -571,7 +585,7 @@ describe("Repository", () => {
|
|
|
571
585
|
status: "active",
|
|
572
586
|
});
|
|
573
587
|
|
|
574
|
-
const persistence =
|
|
588
|
+
const persistence = toPersistenceMapper.build(domain);
|
|
575
589
|
|
|
576
590
|
expect(persistence.id).toBe("123");
|
|
577
591
|
expect(persistence.name).toBe("John");
|
|
@@ -604,7 +618,7 @@ describe("Repository", () => {
|
|
|
604
618
|
},
|
|
605
619
|
];
|
|
606
620
|
|
|
607
|
-
const domainList =
|
|
621
|
+
const domainList = persistenceList.map((p) => toDomainMapper.build(p));
|
|
608
622
|
|
|
609
623
|
expect(domainList).toHaveLength(2);
|
|
610
624
|
expect(domainList[0]).toBeInstanceOf(User);
|
|
@@ -630,7 +644,9 @@ describe("Repository", () => {
|
|
|
630
644
|
}),
|
|
631
645
|
];
|
|
632
646
|
|
|
633
|
-
const persistenceList =
|
|
647
|
+
const persistenceList = domainList.map((d) =>
|
|
648
|
+
toPersistenceMapper.build(d)
|
|
649
|
+
);
|
|
634
650
|
|
|
635
651
|
expect(persistenceList).toHaveLength(2);
|
|
636
652
|
expect(persistenceList[0].id).toBe("1");
|
package/tests/to-json.test.ts
CHANGED
|
@@ -1,91 +1,103 @@
|
|
|
1
|
-
import { Id } from "../src";
|
|
2
|
-
import { Post, User, Address, Comment } from "./utils";
|
|
3
|
-
|
|
4
|
-
describe("toJson Functionality", () => {
|
|
5
|
-
it("should convert simple entity to JSON", () => {
|
|
6
|
-
const post = new Post({
|
|
7
|
-
id: new Id("1"),
|
|
8
|
-
title: "First Post",
|
|
9
|
-
content: "Hello World",
|
|
10
|
-
likes: 5,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const json = post.toJson();
|
|
14
|
-
expect(json).toEqual({
|
|
15
|
-
id: "1",
|
|
16
|
-
title: "First Post",
|
|
17
|
-
content: "Hello World",
|
|
18
|
-
likes: 5,
|
|
19
|
-
});
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("should convert nested entities to JSON", () => {
|
|
23
|
-
const user = new User({
|
|
24
|
-
id: new Id("1"),
|
|
25
|
-
name: "John Doe",
|
|
26
|
-
email: "john@example.com",
|
|
27
|
-
posts: [
|
|
28
|
-
new Post({
|
|
29
|
-
id: new Id("1"),
|
|
30
|
-
title: "Post 1",
|
|
31
|
-
content: "Content 1",
|
|
32
|
-
likes: 0,
|
|
33
|
-
}),
|
|
34
|
-
new Post({
|
|
35
|
-
id: new Id("2"),
|
|
36
|
-
title: "Post 2",
|
|
37
|
-
content: "Content 2",
|
|
38
|
-
likes: 5,
|
|
39
|
-
}),
|
|
40
|
-
],
|
|
41
|
-
address: new Address({
|
|
42
|
-
street: "Main St",
|
|
43
|
-
city: "NYC",
|
|
44
|
-
zipCode: "10001",
|
|
45
|
-
}),
|
|
46
|
-
comments: [
|
|
47
|
-
new Comment({
|
|
48
|
-
id: new Id("1"),
|
|
49
|
-
text: "Great post!",
|
|
50
|
-
author: "Alice",
|
|
51
|
-
}),
|
|
52
|
-
],
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const json = user.toJson();
|
|
56
|
-
|
|
57
|
-
expect(json.id).toBe("1");
|
|
58
|
-
expect(json.name).toBe("John Doe");
|
|
59
|
-
expect(json.posts).toHaveLength(2);
|
|
60
|
-
expect(json.posts[0].title).toBe("Post 1");
|
|
61
|
-
expect(json.address.city).toBe("NYC");
|
|
62
|
-
expect(json.comments[0].text).toBe("Great post!");
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("should handle deeply nested structures", () => {
|
|
66
|
-
const user = new User({
|
|
67
|
-
id: new Id("1"),
|
|
68
|
-
name: "John Doe",
|
|
69
|
-
email: "john@example.com",
|
|
70
|
-
posts: [
|
|
71
|
-
new Post({
|
|
72
|
-
id: new Id("1"),
|
|
73
|
-
title: "Post 1",
|
|
74
|
-
content: "Content 1",
|
|
75
|
-
likes: 0,
|
|
76
|
-
}),
|
|
77
|
-
],
|
|
78
|
-
address: new Address({
|
|
79
|
-
street: "Main St",
|
|
80
|
-
city: "NYC",
|
|
81
|
-
zipCode: "10001",
|
|
82
|
-
}),
|
|
83
|
-
comments: [],
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const json = user.toJson();
|
|
87
|
-
expect(typeof json).toBe("object");
|
|
88
|
-
expect(Array.isArray(json.posts)).toBe(true);
|
|
89
|
-
expect(json.posts[0].id).toBe("1");
|
|
90
|
-
});
|
|
91
|
-
|
|
1
|
+
import { Entity, Id } from "../src";
|
|
2
|
+
import { Post, User, Address, Comment } from "./utils";
|
|
3
|
+
|
|
4
|
+
describe("toJson Functionality", () => {
|
|
5
|
+
it("should convert simple entity to JSON", () => {
|
|
6
|
+
const post = new Post({
|
|
7
|
+
id: new Id("1"),
|
|
8
|
+
title: "First Post",
|
|
9
|
+
content: "Hello World",
|
|
10
|
+
likes: 5,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const json = post.toJson();
|
|
14
|
+
expect(json).toEqual({
|
|
15
|
+
id: "1",
|
|
16
|
+
title: "First Post",
|
|
17
|
+
content: "Hello World",
|
|
18
|
+
likes: 5,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should convert nested entities to JSON", () => {
|
|
23
|
+
const user = new User({
|
|
24
|
+
id: new Id("1"),
|
|
25
|
+
name: "John Doe",
|
|
26
|
+
email: "john@example.com",
|
|
27
|
+
posts: [
|
|
28
|
+
new Post({
|
|
29
|
+
id: new Id("1"),
|
|
30
|
+
title: "Post 1",
|
|
31
|
+
content: "Content 1",
|
|
32
|
+
likes: 0,
|
|
33
|
+
}),
|
|
34
|
+
new Post({
|
|
35
|
+
id: new Id("2"),
|
|
36
|
+
title: "Post 2",
|
|
37
|
+
content: "Content 2",
|
|
38
|
+
likes: 5,
|
|
39
|
+
}),
|
|
40
|
+
],
|
|
41
|
+
address: new Address({
|
|
42
|
+
street: "Main St",
|
|
43
|
+
city: "NYC",
|
|
44
|
+
zipCode: "10001",
|
|
45
|
+
}),
|
|
46
|
+
comments: [
|
|
47
|
+
new Comment({
|
|
48
|
+
id: new Id("1"),
|
|
49
|
+
text: "Great post!",
|
|
50
|
+
author: "Alice",
|
|
51
|
+
}),
|
|
52
|
+
],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const json = user.toJson();
|
|
56
|
+
|
|
57
|
+
expect(json.id).toBe("1");
|
|
58
|
+
expect(json.name).toBe("John Doe");
|
|
59
|
+
expect(json.posts).toHaveLength(2);
|
|
60
|
+
expect(json.posts[0].title).toBe("Post 1");
|
|
61
|
+
expect(json.address.city).toBe("NYC");
|
|
62
|
+
expect(json.comments[0].text).toBe("Great post!");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should handle deeply nested structures", () => {
|
|
66
|
+
const user = new User({
|
|
67
|
+
id: new Id("1"),
|
|
68
|
+
name: "John Doe",
|
|
69
|
+
email: "john@example.com",
|
|
70
|
+
posts: [
|
|
71
|
+
new Post({
|
|
72
|
+
id: new Id("1"),
|
|
73
|
+
title: "Post 1",
|
|
74
|
+
content: "Content 1",
|
|
75
|
+
likes: 0,
|
|
76
|
+
}),
|
|
77
|
+
],
|
|
78
|
+
address: new Address({
|
|
79
|
+
street: "Main St",
|
|
80
|
+
city: "NYC",
|
|
81
|
+
zipCode: "10001",
|
|
82
|
+
}),
|
|
83
|
+
comments: [],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const json = user.toJson();
|
|
87
|
+
expect(typeof json).toBe("object");
|
|
88
|
+
expect(Array.isArray(json.posts)).toBe(true);
|
|
89
|
+
expect(json.posts[0].id).toBe("1");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should serialize date correctly", () => {
|
|
93
|
+
class Test extends Entity<{ id: Id; createdAt: Date }> {}
|
|
94
|
+
|
|
95
|
+
const test = new Test({
|
|
96
|
+
id: new Id("1"),
|
|
97
|
+
createdAt: new Date(),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const json = test.toJson();
|
|
101
|
+
expect(json.createdAt).toBe(test.props.createdAt.toISOString());
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import { Address } from "./utils";
|
|
2
|
-
|
|
3
|
-
describe("Value Object", () => {
|
|
4
|
-
it("should create immutable value object", () => {
|
|
5
|
-
const address = new Address({
|
|
6
|
-
street: "Main St",
|
|
7
|
-
city: "NYC",
|
|
8
|
-
zipCode: "10001",
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
expect(address.street).toBe("Main St");
|
|
12
|
-
expect(address.city).toBe("NYC");
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("should compare value objects by value", () => {
|
|
16
|
-
const address1 = new Address({
|
|
17
|
-
street: "Main St",
|
|
18
|
-
city: "NYC",
|
|
19
|
-
zipCode: "10001",
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const address2 = new Address({
|
|
23
|
-
street: "Main St",
|
|
24
|
-
city: "NYC",
|
|
25
|
-
zipCode: "10001",
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const address3 = new Address({
|
|
29
|
-
street: "Broadway",
|
|
30
|
-
city: "NYC",
|
|
31
|
-
zipCode: "10001",
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
expect(address1.equals(address2)).toBe(true);
|
|
35
|
-
expect(address1.equals(address3)).toBe(false);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("should convert value object to JSON", () => {
|
|
39
|
-
const address = new Address({
|
|
40
|
-
street: "Main St",
|
|
41
|
-
city: "NYC",
|
|
42
|
-
zipCode: "10001",
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const json = address.toJson();
|
|
46
|
-
expect(json).toEqual({
|
|
47
|
-
street: "Main St",
|
|
48
|
-
city: "NYC",
|
|
49
|
-
zipCode: "10001",
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
});
|
|
1
|
+
import { Address } from "./utils";
|
|
2
|
+
|
|
3
|
+
describe("Value Object", () => {
|
|
4
|
+
it("should create immutable value object", () => {
|
|
5
|
+
const address = new Address({
|
|
6
|
+
street: "Main St",
|
|
7
|
+
city: "NYC",
|
|
8
|
+
zipCode: "10001",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
expect(address.street).toBe("Main St");
|
|
12
|
+
expect(address.city).toBe("NYC");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should compare value objects by value", () => {
|
|
16
|
+
const address1 = new Address({
|
|
17
|
+
street: "Main St",
|
|
18
|
+
city: "NYC",
|
|
19
|
+
zipCode: "10001",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const address2 = new Address({
|
|
23
|
+
street: "Main St",
|
|
24
|
+
city: "NYC",
|
|
25
|
+
zipCode: "10001",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const address3 = new Address({
|
|
29
|
+
street: "Broadway",
|
|
30
|
+
city: "NYC",
|
|
31
|
+
zipCode: "10001",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(address1.equals(address2)).toBe(true);
|
|
35
|
+
expect(address1.equals(address3)).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should convert value object to JSON", () => {
|
|
39
|
+
const address = new Address({
|
|
40
|
+
street: "Main St",
|
|
41
|
+
city: "NYC",
|
|
42
|
+
zipCode: "10001",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const json = address.toJson();
|
|
46
|
+
expect(json).toEqual({
|
|
47
|
+
street: "Main St",
|
|
48
|
+
city: "NYC",
|
|
49
|
+
zipCode: "10001",
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|