@woltz/rich-domain 0.2.2 → 1.1.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.
Files changed (148) hide show
  1. package/CHANGELOG.md +23 -75
  2. package/LICENSE +20 -20
  3. package/README.md +37 -20
  4. package/dist/base-entity.d.ts +2 -2
  5. package/dist/base-entity.d.ts.map +1 -1
  6. package/dist/base-entity.js +6 -4
  7. package/dist/base-entity.js.map +1 -1
  8. package/dist/criteria.d.ts +5 -11
  9. package/dist/criteria.d.ts.map +1 -1
  10. package/dist/criteria.js +4 -3
  11. package/dist/criteria.js.map +1 -1
  12. package/dist/deep-proxy.d.ts +3 -1
  13. package/dist/deep-proxy.d.ts.map +1 -1
  14. package/dist/deep-proxy.js +116 -29
  15. package/dist/deep-proxy.js.map +1 -1
  16. package/dist/domain-event-bus.d.ts +5 -6
  17. package/dist/domain-event-bus.d.ts.map +1 -1
  18. package/dist/domain-event-bus.js +3 -11
  19. package/dist/domain-event-bus.js.map +1 -1
  20. package/dist/domain-event.d.ts +1 -31
  21. package/dist/domain-event.d.ts.map +1 -1
  22. package/dist/domain-event.js +2 -1
  23. package/dist/domain-event.js.map +1 -1
  24. package/dist/entity.d.ts +2 -2
  25. package/dist/entity.js +1 -1
  26. package/dist/exceptions.d.ts +251 -0
  27. package/dist/exceptions.d.ts.map +1 -0
  28. package/dist/exceptions.js +321 -0
  29. package/dist/exceptions.js.map +1 -0
  30. package/dist/id.d.ts +3 -3
  31. package/dist/id.d.ts.map +1 -1
  32. package/dist/id.js +15 -4
  33. package/dist/id.js.map +1 -1
  34. package/dist/index.d.ts +2 -5
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -8
  37. package/dist/index.js.map +1 -1
  38. package/dist/paginated-result.d.ts.map +1 -1
  39. package/dist/paginated-result.js +12 -1
  40. package/dist/paginated-result.js.map +1 -1
  41. package/dist/repository/index.d.ts +2 -39
  42. package/dist/repository/index.d.ts.map +1 -1
  43. package/dist/repository/index.js +2 -39
  44. package/dist/repository/index.js.map +1 -1
  45. package/dist/repository/unit-of-work.d.ts +0 -11
  46. package/dist/repository/unit-of-work.d.ts.map +1 -1
  47. package/dist/repository/unit-of-work.js +0 -35
  48. package/dist/repository/unit-of-work.js.map +1 -1
  49. package/dist/types/criteria.d.ts +6 -2
  50. package/dist/types/criteria.d.ts.map +1 -1
  51. package/dist/types/criteria.js +1 -1
  52. package/dist/types/criteria.js.map +1 -1
  53. package/dist/types/domain-event.d.ts +32 -0
  54. package/dist/types/domain-event.d.ts.map +1 -0
  55. package/dist/types/domain-event.js +2 -0
  56. package/dist/types/domain-event.js.map +1 -0
  57. package/dist/types/domain.d.ts +2 -2
  58. package/dist/types/domain.d.ts.map +1 -1
  59. package/dist/types/history-tracker.d.ts +1 -1
  60. package/dist/types/history-tracker.d.ts.map +1 -1
  61. package/dist/types/index.d.ts +1 -0
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/index.js +1 -0
  64. package/dist/types/index.js.map +1 -1
  65. package/dist/value-object.d.ts +1 -1
  66. package/dist/value-object.d.ts.map +1 -1
  67. package/dist/value-object.js +2 -5
  68. package/dist/value-object.js.map +1 -1
  69. package/eslint.config.js +3 -3
  70. package/jest.config.js +1 -1
  71. package/package.json +14 -20
  72. package/src/base-entity.ts +6 -5
  73. package/src/criteria.ts +11 -11
  74. package/src/deep-proxy.ts +447 -339
  75. package/src/domain-event-bus.ts +152 -166
  76. package/src/domain-event.ts +53 -90
  77. package/src/entity.ts +16 -16
  78. package/src/exceptions.ts +435 -0
  79. package/src/id.ts +107 -94
  80. package/src/index.ts +26 -9
  81. package/src/paginated-result.ts +14 -1
  82. package/src/repository/index.ts +2 -44
  83. package/src/repository/unit-of-work.ts +1 -44
  84. package/src/types/criteria.ts +7 -2
  85. package/src/types/domain-event.ts +38 -0
  86. package/src/types/domain.ts +2 -3
  87. package/src/types/history-tracker.ts +1 -1
  88. package/src/types/index.ts +1 -0
  89. package/src/validation-error.ts +97 -97
  90. package/src/value-object.ts +3 -6
  91. package/tests/criteria.test.ts +8 -0
  92. package/tests/domain-events.test.ts +431 -445
  93. package/tests/entity-validation.test.ts +2 -2
  94. package/tests/entity.test.ts +33 -33
  95. package/tests/history-tracker.spec.ts +57 -17
  96. package/tests/id.test.ts +341 -341
  97. package/tests/repository.test.ts +8 -4
  98. package/tests/to-json.test.ts +103 -91
  99. package/tests/utils.ts +254 -151
  100. package/tests/value-object-validation.test.ts +0 -9
  101. package/tests/value-objects.test.ts +52 -52
  102. package/tsconfig.json +2 -24
  103. package/.github/workflows/ci.yml +0 -40
  104. package/.husky/commit-msg +0 -1
  105. package/.husky/pre-commit +0 -1
  106. package/.vscode/settings.json +0 -3
  107. package/commitlint.config.js +0 -23
  108. package/dist/filtering.d.ts +0 -107
  109. package/dist/filtering.d.ts.map +0 -1
  110. package/dist/filtering.js +0 -202
  111. package/dist/filtering.js.map +0 -1
  112. package/dist/ordering.d.ts +0 -93
  113. package/dist/ordering.d.ts.map +0 -1
  114. package/dist/ordering.js +0 -154
  115. package/dist/ordering.js.map +0 -1
  116. package/dist/pagination.d.ts +0 -218
  117. package/dist/pagination.d.ts.map +0 -1
  118. package/dist/pagination.js +0 -281
  119. package/dist/pagination.js.map +0 -1
  120. package/dist/repository/in-memory-repository.d.ts +0 -50
  121. package/dist/repository/in-memory-repository.d.ts.map +0 -1
  122. package/dist/repository/in-memory-repository.js +0 -93
  123. package/dist/repository/in-memory-repository.js.map +0 -1
  124. package/dist/repository/mapper.d.ts +0 -56
  125. package/dist/repository/mapper.d.ts.map +0 -1
  126. package/dist/repository/mapper.js +0 -15
  127. package/dist/repository/mapper.js.map +0 -1
  128. package/dist/repository/types.d.ts +0 -87
  129. package/dist/repository/types.d.ts.map +0 -1
  130. package/dist/repository/types.js +0 -6
  131. package/dist/repository/types.js.map +0 -1
  132. package/dist/repository.d.ts +0 -2
  133. package/dist/repository.d.ts.map +0 -1
  134. package/dist/repository.js +0 -21
  135. package/dist/repository.js.map +0 -1
  136. package/dist/specification.d.ts +0 -102
  137. package/dist/specification.d.ts.map +0 -1
  138. package/dist/specification.js +0 -187
  139. package/dist/specification.js.map +0 -1
  140. package/dist/types/repository.d.ts +0 -43
  141. package/dist/types/repository.d.ts.map +0 -1
  142. package/dist/types/repository.js +0 -2
  143. package/dist/types/repository.js.map +0 -1
  144. package/dist/types.d.ts +0 -88
  145. package/dist/types.d.ts.map +0 -1
  146. package/dist/types.js +0 -12
  147. package/dist/types.js.map +0 -1
  148. package/src/repository/in-memory-repository.ts +0 -116
@@ -1,6 +1,8 @@
1
- import { Id, Aggregate, Criteria, BaseProps, PaginatedResult } from "../src";
2
- import { InMemoryRepository, Mapper } from "../src/repository";
1
+ import { Id, Aggregate, Criteria, PaginatedResult } from "../src";
2
+ import { Mapper } from "../src/repository";
3
3
  import { Repository } from "../src/repository/base-repository";
4
+ import { BaseProps } from "../src/types";
5
+ import { InMemoryRepository } from "./utils";
4
6
 
5
7
  // ============================================================================
6
8
  // Test Domain Models
@@ -482,7 +484,7 @@ describe("Repository", () => {
482
484
  });
483
485
 
484
486
  it("should save new user (insert)", async () => {
485
- expect(user.isNew).toBe(true);
487
+ expect(user.isNew()).toBe(true);
486
488
  await repository.create(user);
487
489
 
488
490
  const found = await repository.findById(user.id.value);
@@ -644,7 +646,9 @@ describe("Repository", () => {
644
646
  }),
645
647
  ];
646
648
 
647
- const persistenceList = domainList.map((d) => toPersistenceMapper.build(d));
649
+ const persistenceList = domainList.map((d) =>
650
+ toPersistenceMapper.build(d)
651
+ );
648
652
 
649
653
  expect(persistenceList).toHaveLength(2);
650
654
  expect(persistenceList[0].id).toBe("1");
@@ -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
+ });
package/tests/utils.ts CHANGED
@@ -1,151 +1,254 @@
1
- // ============================================================================
2
- // Test Entities & Value Objects
3
- // ============================================================================
4
-
5
- import { Aggregate, Entity, Id, ValueObject } from "../src";
6
-
7
- interface AddressProps {
8
- street: string;
9
- city: string;
10
- zipCode: string;
11
- }
12
-
13
- class Address extends ValueObject<AddressProps> {
14
- get street(): string {
15
- return this.props.street;
16
- }
17
-
18
- get city(): string {
19
- return this.props.city;
20
- }
21
-
22
- get zipCode(): string {
23
- return this.props.zipCode;
24
- }
25
- }
26
-
27
- interface PostProps {
28
- id: Id;
29
- title: string;
30
- content: string;
31
- likes: number;
32
- }
33
-
34
- class Post extends Entity<PostProps> {
35
- get title(): string {
36
- return this.props.title;
37
- }
38
-
39
- set title(value: string) {
40
- this.props.title = value;
41
- }
42
-
43
- get content(): string {
44
- return this.props.content;
45
- }
46
-
47
- set content(value: string) {
48
- this.props.content = value;
49
- }
50
-
51
- get likes(): number {
52
- return this.props.likes;
53
- }
54
-
55
- set likes(value: number) {
56
- this.props.likes = value;
57
- }
58
- }
59
-
60
- interface CommentProps {
61
- id: Id;
62
- text: string;
63
- author: string;
64
- }
65
-
66
- class Comment extends Entity<CommentProps> {
67
- get text(): string {
68
- return this.props.text;
69
- }
70
-
71
- set text(value: string) {
72
- this.props.text = value;
73
- }
74
-
75
- get author(): string {
76
- return this.props.author;
77
- }
78
- }
79
-
80
- interface UserProps {
81
- id: Id;
82
- name: string;
83
- email: string;
84
- posts: Post[];
85
- address: Address;
86
- comments: Comment[];
87
- extra?: {
88
- age: number;
89
- height: number;
90
- };
91
- }
92
-
93
- class User extends Aggregate<UserProps> {
94
- get name(): string {
95
- return this.props.name;
96
- }
97
-
98
- set name(value: string) {
99
- this.props.name = value;
100
- }
101
-
102
- get email(): string {
103
- return this.props.email;
104
- }
105
-
106
- get posts(): Post[] {
107
- return this.props.posts;
108
- }
109
-
110
- set posts(value: Post[]) {
111
- this.props.posts = value;
112
- }
113
-
114
- get address(): Address {
115
- return this.props.address;
116
- }
117
-
118
- set address(value: Address) {
119
- this.props.address = value;
120
- }
121
-
122
- get comments(): Comment[] {
123
- return this.props.comments;
124
- }
125
-
126
- set comments(value: Comment[]) {
127
- this.props.comments = value;
128
- }
129
-
130
- public addPost(post: Post) {
131
- this.props.posts.push(post);
132
- }
133
-
134
- public addManyPosts(posts: Post[]) {
135
- this.props.posts.push(...posts);
136
- }
137
-
138
- public removePostById(id: string) {
139
- this.props.posts = this.props.posts.filter((post) => post.id.value !== id);
140
- }
141
-
142
- public changeEmail(email: string) {
143
- this.props.email = email;
144
- }
145
-
146
- public changeExtra(extra: { age: number; height: number }) {
147
- this.props.extra = extra;
148
- }
149
- }
150
-
151
- export { User, Post, Comment, Address };
1
+ // ============================================================================
2
+ // Test Entities & Value Objects
3
+ // ============================================================================
4
+
5
+ import {
6
+ Aggregate,
7
+ Criteria,
8
+ Entity,
9
+ Id,
10
+ Mapper,
11
+ PaginatedResult,
12
+ Repository,
13
+ UnitOfWork,
14
+ ValueObject,
15
+ } from "../src";
16
+
17
+ interface AddressProps {
18
+ street: string;
19
+ city: string;
20
+ zipCode: string;
21
+ }
22
+
23
+ class Address extends ValueObject<AddressProps> {
24
+ get street(): string {
25
+ return this.props.street;
26
+ }
27
+
28
+ get city(): string {
29
+ return this.props.city;
30
+ }
31
+
32
+ get zipCode(): string {
33
+ return this.props.zipCode;
34
+ }
35
+ }
36
+
37
+ interface PostProps {
38
+ id: Id;
39
+ title: string;
40
+ content: string;
41
+ likes: number;
42
+ }
43
+
44
+ class Post extends Entity<PostProps> {
45
+ get title(): string {
46
+ return this.props.title;
47
+ }
48
+
49
+ set title(value: string) {
50
+ this.props.title = value;
51
+ }
52
+
53
+ get content(): string {
54
+ return this.props.content;
55
+ }
56
+
57
+ set content(value: string) {
58
+ this.props.content = value;
59
+ }
60
+
61
+ get likes(): number {
62
+ return this.props.likes;
63
+ }
64
+
65
+ set likes(value: number) {
66
+ this.props.likes = value;
67
+ }
68
+ }
69
+
70
+ interface CommentProps {
71
+ id: Id;
72
+ text: string;
73
+ author: string;
74
+ }
75
+
76
+ class Comment extends Entity<CommentProps> {
77
+ get text(): string {
78
+ return this.props.text;
79
+ }
80
+
81
+ set text(value: string) {
82
+ this.props.text = value;
83
+ }
84
+
85
+ get author(): string {
86
+ return this.props.author;
87
+ }
88
+ }
89
+
90
+ interface UserProps {
91
+ id: Id;
92
+ name: string;
93
+ email: string;
94
+ posts: Post[];
95
+ address: Address;
96
+ comments: Comment[];
97
+ extra?: {
98
+ age: number;
99
+ height: number;
100
+ };
101
+ }
102
+
103
+ class User extends Aggregate<UserProps> {
104
+ get name(): string {
105
+ return this.props.name;
106
+ }
107
+
108
+ set name(value: string) {
109
+ this.props.name = value;
110
+ }
111
+
112
+ get email(): string {
113
+ return this.props.email;
114
+ }
115
+
116
+ get posts(): Post[] {
117
+ return this.props.posts;
118
+ }
119
+
120
+ set posts(value: Post[]) {
121
+ this.props.posts = value;
122
+ }
123
+
124
+ get address(): Address {
125
+ return this.props.address;
126
+ }
127
+
128
+ set address(value: Address) {
129
+ this.props.address = value;
130
+ }
131
+
132
+ get comments(): Comment[] {
133
+ return this.props.comments;
134
+ }
135
+
136
+ set comments(value: Comment[]) {
137
+ this.props.comments = value;
138
+ }
139
+
140
+ public addPost(post: Post) {
141
+ this.props.posts.push(post);
142
+ }
143
+
144
+ public addManyPosts(posts: Post[]) {
145
+ this.props.posts.push(...posts);
146
+ }
147
+
148
+ public removePostById(id: string) {
149
+ this.props.posts = this.props.posts.filter((post) => post.id.value !== id);
150
+ }
151
+
152
+ public changeEmail(email: string) {
153
+ this.props.email = email;
154
+ }
155
+
156
+ public changeExtra(extra: { age: number; height: number }) {
157
+ this.props.extra = extra;
158
+ }
159
+ }
160
+
161
+ class InMemoryRepository<
162
+ TDomain extends Aggregate<any>
163
+ > extends Repository<TDomain> {
164
+ protected items: Map<string, TDomain> = new Map();
165
+ readonly uow: UnitOfWork;
166
+ constructor(
167
+ protected readonly mapperToDomain: Mapper<unknown, TDomain>,
168
+ protected readonly mapperToPersistence: Mapper<TDomain, unknown>
169
+ ) {
170
+ super();
171
+ this.uow = {} as UnitOfWork;
172
+ }
173
+
174
+ get model(): any {
175
+ // your database table name
176
+ return "inMemory";
177
+ }
178
+
179
+ async findById(id: string): Promise<TDomain | null> {
180
+ return this.items.get(id) || null;
181
+ }
182
+
183
+ async find(criteria: Criteria<TDomain>): Promise<PaginatedResult<TDomain>> {
184
+ const allItems = Array.from(this.items.values());
185
+ return PaginatedResult.fromArray(allItems, criteria);
186
+ }
187
+
188
+ async findAll(criteria?: Criteria<TDomain>): Promise<TDomain[]> {
189
+ if (criteria) {
190
+ const result = await this.find(criteria);
191
+ return result.data;
192
+ }
193
+
194
+ return Array.from(this.items.values());
195
+ }
196
+
197
+ async findOne(criteria: Criteria<TDomain>): Promise<TDomain | null> {
198
+ const result = await this.find(criteria.clone().limit(1));
199
+ return result.data.length > 0 ? result.data[0] : null;
200
+ }
201
+
202
+ async create(aggregate: TDomain): Promise<void> {
203
+ this.items.set(aggregate.id.value, aggregate);
204
+ }
205
+
206
+ async update(entity: TDomain): Promise<void> {
207
+ this.items.set(entity.id.value, entity);
208
+ }
209
+
210
+ async createMany(aggregates: TDomain[]): Promise<void> {
211
+ for (const aggregate of aggregates) {
212
+ await this.create(aggregate);
213
+ }
214
+ }
215
+
216
+ async delete(aggregate: TDomain): Promise<void> {
217
+ this.items.delete(aggregate.id.value);
218
+ }
219
+
220
+ async exists(id: string): Promise<boolean> {
221
+ return this.items.has(id);
222
+ }
223
+
224
+ async count(criteria?: Criteria<TDomain>): Promise<number> {
225
+ if (criteria) {
226
+ const result = await this.find(criteria);
227
+ return result.meta.total;
228
+ }
229
+ return this.items.size;
230
+ }
231
+
232
+ /**
233
+ * Clear all items (useful for test cleanup)
234
+ */
235
+ clear(): void {
236
+ this.items.clear();
237
+ }
238
+
239
+ /**
240
+ * Get all items as array (useful for debugging)
241
+ */
242
+ getAll(): TDomain[] {
243
+ return Array.from(this.items.values());
244
+ }
245
+
246
+ /**
247
+ * Get items count
248
+ */
249
+ size(): number {
250
+ return this.items.size;
251
+ }
252
+ }
253
+
254
+ export { User, Post, Comment, Address, InMemoryRepository };
@@ -54,9 +54,6 @@ class Money extends ValueObject<MoneyProps> {
54
54
  };
55
55
 
56
56
  protected static hooks: VOHooks<MoneyProps, Money> = {
57
- defaultValues: {
58
- currency: "USD",
59
- },
60
57
  rules: (money) => {
61
58
  if (money.amount > 1000000) {
62
59
  throwValidationError("amount", "Amount cannot exceed 1,000,000");
@@ -135,12 +132,6 @@ describe("ValueObject with Validation", () => {
135
132
  expect(money.currency).toBe("USD");
136
133
  });
137
134
 
138
- it("should apply default currency", () => {
139
- const money = new Money({ amount: 50 } as any);
140
- expect(money.amount).toBe(50);
141
- expect(money.currency).toBe("USD");
142
- });
143
-
144
135
  it("should throw on negative amount", () => {
145
136
  expect(() => {
146
137
  new Money({ amount: -10, currency: "USD" });