@zeeshan60/event-processor 1.0.4 → 1.0.5

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 (34) hide show
  1. package/dist/ActivityEventHandler.d.ts +12 -0
  2. package/dist/ActivityEventHandler.d.ts.map +1 -0
  3. package/dist/ActivityEventHandler.js +35 -0
  4. package/dist/FriendEventHandler.d.ts +21 -0
  5. package/dist/FriendEventHandler.d.ts.map +1 -0
  6. package/dist/FriendEventHandler.js +175 -0
  7. package/dist/GroupEventHandler.d.ts +25 -0
  8. package/dist/GroupEventHandler.d.ts.map +1 -0
  9. package/dist/GroupEventHandler.js +270 -0
  10. package/dist/GroupTransactionEventHandler.d.ts +25 -0
  11. package/dist/GroupTransactionEventHandler.d.ts.map +1 -0
  12. package/dist/GroupTransactionEventHandler.js +296 -0
  13. package/dist/TransactionEventHandler.d.ts +11 -7
  14. package/dist/TransactionEventHandler.d.ts.map +1 -1
  15. package/dist/TransactionEventHandler.js +139 -10
  16. package/dist/UserEventHandler.d.ts +17 -0
  17. package/dist/UserEventHandler.d.ts.map +1 -0
  18. package/dist/UserEventHandler.js +82 -0
  19. package/dist/events.d.ts +30 -0
  20. package/dist/events.d.ts.map +1 -0
  21. package/dist/events.js +60 -0
  22. package/dist/index.d.ts +1 -21
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +16 -86
  25. package/dist/utils/eventConverter.d.ts +23 -0
  26. package/dist/utils/eventConverter.d.ts.map +1 -0
  27. package/dist/utils/eventConverter.js +370 -0
  28. package/dist/utils/splitTypeUtils.d.ts +7 -0
  29. package/dist/utils/splitTypeUtils.d.ts.map +1 -0
  30. package/dist/utils/splitTypeUtils.js +45 -0
  31. package/dist/utils/userPathUtils.d.ts +6 -0
  32. package/dist/utils/userPathUtils.d.ts.map +1 -0
  33. package/dist/utils/userPathUtils.js +16 -0
  34. package/package.json +1 -1
@@ -0,0 +1,12 @@
1
+ import { Event, Model } from '.';
2
+ import { ActivityLogModelStore } from '.';
3
+ import { ActivityLogEventStore } from '.';
4
+ import { UserModelStore } from '.';
5
+ export declare class ActivityEventHandler {
6
+ private activityLogModelStore;
7
+ private activityLogEventStore;
8
+ private userModelStore;
9
+ constructor(activityLogModelStore: ActivityLogModelStore, activityLogEventStore: ActivityLogEventStore, userModelStore: UserModelStore);
10
+ createActivityLog(event: Event, existingModel: Model | undefined, updatedModel: Model): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=ActivityEventHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActivityEventHandler.d.ts","sourceRoot":"","sources":["../src/ActivityEventHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAE,KAAK,EAA8C,MAAM,GAAG,CAAC;AAC5E,OAAO,EAAC,qBAAqB,EAAC,MAAM,GAAG,CAAC;AACxC,OAAO,EAAC,qBAAqB,EAAC,MAAM,GAAG,CAAC;AACxC,OAAO,EAAC,cAAc,EAAC,MAAM,GAAG,CAAC;AAEjC,qBAAa,oBAAoB;IAEzB,OAAO,CAAC,qBAAqB;IAC7B,OAAO,CAAC,qBAAqB;IAC7B,OAAO,CAAC,cAAc;gBAFd,qBAAqB,EAAE,qBAAqB,EAC5C,qBAAqB,EAAE,qBAAqB,EAC5C,cAAc,EAAE,cAAc;IAGpC,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,GAAG,SAAS,EAAE,YAAY,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;CA2B9G"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActivityEventHandler = void 0;
4
+ const _1 = require(".");
5
+ class ActivityEventHandler {
6
+ constructor(activityLogModelStore, activityLogEventStore, userModelStore) {
7
+ this.activityLogModelStore = activityLogModelStore;
8
+ this.activityLogEventStore = activityLogEventStore;
9
+ this.userModelStore = userModelStore;
10
+ }
11
+ async createActivityLog(event, existingModel, updatedModel) {
12
+ if (!event.activityLog) {
13
+ return;
14
+ }
15
+ let actorName;
16
+ if (event.createdBy !== updatedModel.userId) {
17
+ const actorUser = await this.userModelStore.getByStreamId(event.createdBy);
18
+ if (actorUser) {
19
+ actorName = actorUser.displayName;
20
+ }
21
+ else {
22
+ actorName = event.createdBy;
23
+ }
24
+ }
25
+ const activityLogProps = event.activityLog(existingModel, actorName);
26
+ if (!activityLogProps) {
27
+ return;
28
+ }
29
+ const activityLogEvent = new _1.ActivityLogCreated(activityLogProps);
30
+ const activityLogModel = activityLogEvent.apply();
31
+ await this.activityLogEventStore.addEvent(updatedModel.userId, activityLogEvent);
32
+ await this.activityLogModelStore.save(activityLogModel);
33
+ }
34
+ }
35
+ exports.ActivityEventHandler = ActivityEventHandler;
@@ -0,0 +1,21 @@
1
+ import { FriendCreated, FriendDeleted, FriendIdAdded, FriendIdRemoved, FriendModel, FriendUpdated, Event } from '.';
2
+ import { FriendModelStore } from '.';
3
+ import { UserModelStore } from '.';
4
+ import { FriendEventStore } from '.';
5
+ import { UserEventStore } from '.';
6
+ import { ActivityEventHandler } from './ActivityEventHandler';
7
+ export declare class FriendEventHandler {
8
+ private modelStore;
9
+ private userModelStore;
10
+ private friendEventStore;
11
+ private userEventStore;
12
+ private activityEventHandler?;
13
+ constructor(modelStore: FriendModelStore, userModelStore: UserModelStore, friendEventStore: FriendEventStore, userEventStore: UserEventStore, activityEventHandler?: ActivityEventHandler | undefined);
14
+ handleEvent(event: Event): Promise<FriendModel>;
15
+ handleFriendCreated(event: FriendCreated): Promise<FriendModel>;
16
+ handleFriendUpdated(event: FriendUpdated): Promise<FriendModel>;
17
+ handleFriendDeleted(event: FriendDeleted): Promise<FriendModel>;
18
+ handleFriendIdAdded(event: FriendIdAdded): Promise<FriendModel>;
19
+ handleFriendIdRemoved(event: FriendIdRemoved): Promise<FriendModel>;
20
+ }
21
+ //# sourceMappingURL=FriendEventHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FriendEventHandler.d.ts","sourceRoot":"","sources":["../src/FriendEventHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,WAAW,EACX,aAAa,EAGb,KAAK,EACR,MAAM,GAAG,CAAC;AACX,OAAO,EAAC,gBAAgB,EAAC,MAAM,GAAG,CAAC;AACnC,OAAO,EAAC,cAAc,EAAC,MAAM,GAAG,CAAC;AACjC,OAAO,EAAC,gBAAgB,EAAC,MAAM,GAAG,CAAC;AACnC,OAAO,EAAC,cAAc,EAAC,MAAM,GAAG,CAAC;AACjC,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAG5D,qBAAa,kBAAkB;IAEvB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,oBAAoB,CAAC;gBAJrB,UAAU,EAAE,gBAAgB,EAC5B,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,cAAc,EAC9B,oBAAoB,CAAC,EAAE,oBAAoB,YAAA;IAGjD,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;IA8B/C,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAwG/D,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAU/D,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAU/D,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAU/D,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC;CAS5E"}
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FriendEventHandler = void 0;
4
+ const _1 = require(".");
5
+ const uuid_1 = require("uuid");
6
+ class FriendEventHandler {
7
+ constructor(modelStore, userModelStore, friendEventStore, userEventStore, activityEventHandler) {
8
+ this.modelStore = modelStore;
9
+ this.userModelStore = userModelStore;
10
+ this.friendEventStore = friendEventStore;
11
+ this.userEventStore = userEventStore;
12
+ this.activityEventHandler = activityEventHandler;
13
+ }
14
+ async handleEvent(event) {
15
+ const validEventTypes = [
16
+ 'FriendCreated',
17
+ 'FriendUpdated',
18
+ 'FriendDeleted',
19
+ 'FriendIdAdded',
20
+ 'FriendIdRemoved'
21
+ ];
22
+ const eventType = event.constructor.name;
23
+ if (!validEventTypes.includes(eventType)) {
24
+ throw new Error(`Unknown friend event type: ${eventType}`);
25
+ }
26
+ switch (eventType) {
27
+ case 'FriendCreated':
28
+ return await this.handleFriendCreated(event);
29
+ case 'FriendUpdated':
30
+ return await this.handleFriendUpdated(event);
31
+ case 'FriendDeleted':
32
+ return await this.handleFriendDeleted(event);
33
+ case 'FriendIdAdded':
34
+ return await this.handleFriendIdAdded(event);
35
+ case 'FriendIdRemoved':
36
+ return await this.handleFriendIdRemoved(event);
37
+ default:
38
+ throw new Error(`Unknown friend event type: ${eventType}`);
39
+ }
40
+ }
41
+ async handleFriendCreated(event) {
42
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
43
+ const updatedModel = event.apply(existingModel);
44
+ await this.modelStore.save(updatedModel);
45
+ // Check if friend is already a user (try phone first, then email)
46
+ let friendUser = null;
47
+ if (event.friendPhoneNumber) {
48
+ friendUser = await this.userModelStore.findByPhone(event.friendPhoneNumber);
49
+ }
50
+ if (!friendUser && event.friendEmail) {
51
+ friendUser = await this.userModelStore.findByEmail(event.friendEmail);
52
+ }
53
+ // If friend is a user, link them and create reciprocal friendship
54
+ if (friendUser) {
55
+ // Create FriendIdAdded event for current user
56
+ const friendIdAddedEvent = new _1.FriendIdAdded({
57
+ userId: event.userId,
58
+ friendId: friendUser.userId,
59
+ createdAt: new Date(),
60
+ createdBy: event.userId,
61
+ streamId: event.streamId,
62
+ version: updatedModel.version + 1,
63
+ });
64
+ await this.friendEventStore.addEvent(event.userId, friendIdAddedEvent);
65
+ const modelWithFriendId = friendIdAddedEvent.apply(updatedModel);
66
+ await this.modelStore.save(modelWithFriendId);
67
+ const primaryUser = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(event.userId);
68
+ if (primaryUser) {
69
+ const reciprocalFriendCreated = new _1.FriendCreated({
70
+ userId: friendUser.userId,
71
+ friendEmail: primaryUser.email,
72
+ friendPhoneNumber: primaryUser.phoneNumber,
73
+ friendDisplayName: primaryUser.displayName,
74
+ friendId: event.userId,
75
+ groupId: event.groupId,
76
+ createdAt: new Date(),
77
+ createdBy: friendUser.userId,
78
+ streamId: `stream-${(0, uuid_1.v4)()}`,
79
+ version: 1,
80
+ });
81
+ await this.friendEventStore.addEvent(friendUser.userId, reciprocalFriendCreated);
82
+ const reciprocalModel = reciprocalFriendCreated.apply(undefined);
83
+ await this.modelStore.save(reciprocalModel);
84
+ }
85
+ return modelWithFriendId;
86
+ }
87
+ else {
88
+ // Friend user not found - create placeholder user
89
+ const placeholderStreamId = `stream-${(0, uuid_1.v4)()}`;
90
+ const placeholderUserCreated = new _1.PlaceholderUserCreated({
91
+ userId: placeholderStreamId,
92
+ displayName: event.friendDisplayName,
93
+ phoneNumber: event.friendPhoneNumber,
94
+ email: event.friendEmail,
95
+ createdAt: new Date(),
96
+ createdBy: event.userId,
97
+ streamId: placeholderStreamId,
98
+ version: 1,
99
+ });
100
+ await this.userEventStore.addEvent(placeholderStreamId, placeholderUserCreated);
101
+ const placeholderUser = placeholderUserCreated.apply(undefined);
102
+ await this.userModelStore.save(placeholderUser);
103
+ // Link primary user to placeholder
104
+ const friendIdAddedEvent = new _1.FriendIdAdded({
105
+ userId: event.userId,
106
+ friendId: placeholderStreamId,
107
+ createdAt: new Date(),
108
+ createdBy: event.userId,
109
+ streamId: event.streamId,
110
+ version: updatedModel.version + 1,
111
+ });
112
+ await this.friendEventStore.addEvent(event.userId, friendIdAddedEvent);
113
+ const modelWithPlaceholderId = friendIdAddedEvent.apply(updatedModel);
114
+ await this.modelStore.save(modelWithPlaceholderId);
115
+ // Create reciprocal friendship for placeholder user
116
+ const primaryUser = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(event.userId);
117
+ if (primaryUser) {
118
+ const primaryUserModel = primaryUser;
119
+ const reciprocalFriendCreated = new _1.FriendCreated({
120
+ userId: placeholderStreamId,
121
+ friendEmail: primaryUserModel.email,
122
+ friendPhoneNumber: primaryUserModel.phoneNumber,
123
+ friendDisplayName: primaryUserModel.displayName,
124
+ friendId: event.userId,
125
+ groupId: event.groupId,
126
+ createdAt: new Date(),
127
+ createdBy: placeholderStreamId,
128
+ streamId: `stream-${(0, uuid_1.v4)()}`,
129
+ version: 1,
130
+ });
131
+ await this.friendEventStore.addEvent(placeholderStreamId, reciprocalFriendCreated);
132
+ const reciprocalModel = reciprocalFriendCreated.apply(undefined);
133
+ await this.modelStore.save(reciprocalModel);
134
+ }
135
+ return modelWithPlaceholderId;
136
+ }
137
+ }
138
+ async handleFriendUpdated(event) {
139
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
140
+ const updatedModel = event.apply(existingModel);
141
+ await this.modelStore.save(updatedModel);
142
+ if (this.activityEventHandler) {
143
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
144
+ }
145
+ return updatedModel;
146
+ }
147
+ async handleFriendDeleted(event) {
148
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
149
+ const updatedModel = event.apply(existingModel);
150
+ await this.modelStore.save(updatedModel);
151
+ if (this.activityEventHandler) {
152
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
153
+ }
154
+ return updatedModel;
155
+ }
156
+ async handleFriendIdAdded(event) {
157
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
158
+ const updatedModel = event.apply(existingModel);
159
+ await this.modelStore.save(updatedModel);
160
+ if (this.activityEventHandler) {
161
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
162
+ }
163
+ return updatedModel;
164
+ }
165
+ async handleFriendIdRemoved(event) {
166
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
167
+ const updatedModel = event.apply(existingModel);
168
+ await this.modelStore.save(updatedModel);
169
+ if (this.activityEventHandler) {
170
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
171
+ }
172
+ return updatedModel;
173
+ }
174
+ }
175
+ exports.FriendEventHandler = FriendEventHandler;
@@ -0,0 +1,25 @@
1
+ import { GroupCreated, GroupNameChanged, GroupDescriptionChanged, GroupMembersAdded, GroupMembersRemoved, GroupDeleted, GroupModel, Event } from '.';
2
+ import { GroupModelStore } from '.';
3
+ import { FriendModelStore } from '.';
4
+ import { UserModelStore } from '.';
5
+ import { GroupEventStore } from '.';
6
+ import { FriendEventStore } from '.';
7
+ import { ActivityEventHandler } from './ActivityEventHandler';
8
+ export declare class GroupEventHandler {
9
+ private modelStore;
10
+ private friendModelStore;
11
+ private userModelStore;
12
+ private groupEventStore;
13
+ private friendEventStore;
14
+ private activityEventHandler?;
15
+ constructor(modelStore: GroupModelStore, friendModelStore: FriendModelStore, userModelStore: UserModelStore, groupEventStore: GroupEventStore, friendEventStore: FriendEventStore, activityEventHandler?: ActivityEventHandler | undefined);
16
+ handleEvent(event: Event): Promise<GroupModel>;
17
+ private ensureBidirectionalFriendship;
18
+ handleGroupCreated(event: GroupCreated): Promise<GroupModel>;
19
+ handleGroupNameChanged(event: GroupNameChanged): Promise<GroupModel>;
20
+ handleGroupDescriptionChanged(event: GroupDescriptionChanged): Promise<GroupModel>;
21
+ handleGroupMembersAdded(event: GroupMembersAdded): Promise<GroupModel>;
22
+ handleGroupMembersRemoved(event: GroupMembersRemoved): Promise<GroupModel>;
23
+ handleGroupDeleted(event: GroupDeleted): Promise<GroupModel>;
24
+ }
25
+ //# sourceMappingURL=GroupEventHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupEventHandler.d.ts","sourceRoot":"","sources":["../src/GroupEventHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,UAAU,EAEV,KAAK,EACR,MAAM,GAAG,CAAC;AACX,OAAO,EAAC,eAAe,EAAC,MAAM,GAAG,CAAC;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,GAAG,CAAC;AACnC,OAAO,EAAC,cAAc,EAAC,MAAM,GAAG,CAAC;AACjC,OAAO,EAAC,eAAe,EAAC,MAAM,GAAG,CAAC;AAClC,OAAO,EAAC,gBAAgB,EAAC,MAAM,GAAG,CAAC;AACnC,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAG5D,qBAAa,iBAAiB;IAEtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,oBAAoB,CAAC;gBALrB,UAAU,EAAE,eAAe,EAC3B,gBAAgB,EAAE,gBAAgB,EAClC,cAAc,EAAE,cAAc,EAC9B,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,gBAAgB,EAClC,oBAAoB,CAAC,EAAE,oBAAoB,YAAA;IAGjD,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;YAiCtC,6BAA6B;IA8DrC,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;IA8C5D,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BpE,6BAA6B,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BlF,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAoEtE,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IA8B1E,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;CAWrE"}
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GroupEventHandler = void 0;
4
+ const _1 = require(".");
5
+ const uuid_1 = require("uuid");
6
+ class GroupEventHandler {
7
+ constructor(modelStore, friendModelStore, userModelStore, groupEventStore, friendEventStore, activityEventHandler) {
8
+ this.modelStore = modelStore;
9
+ this.friendModelStore = friendModelStore;
10
+ this.userModelStore = userModelStore;
11
+ this.groupEventStore = groupEventStore;
12
+ this.friendEventStore = friendEventStore;
13
+ this.activityEventHandler = activityEventHandler;
14
+ }
15
+ async handleEvent(event) {
16
+ const validEventTypes = [
17
+ 'GroupCreated',
18
+ 'GroupNameChanged',
19
+ 'GroupDescriptionChanged',
20
+ 'GroupMembersAdded',
21
+ 'GroupMembersRemoved',
22
+ 'GroupDeleted'
23
+ ];
24
+ const eventType = event.constructor.name;
25
+ if (!validEventTypes.includes(eventType)) {
26
+ throw new Error(`Unknown group event type: ${eventType}`);
27
+ }
28
+ switch (eventType) {
29
+ case 'GroupCreated':
30
+ return await this.handleGroupCreated(event);
31
+ case 'GroupNameChanged':
32
+ return await this.handleGroupNameChanged(event);
33
+ case 'GroupDescriptionChanged':
34
+ return await this.handleGroupDescriptionChanged(event);
35
+ case 'GroupMembersAdded':
36
+ return await this.handleGroupMembersAdded(event);
37
+ case 'GroupMembersRemoved':
38
+ return await this.handleGroupMembersRemoved(event);
39
+ case 'GroupDeleted':
40
+ return await this.handleGroupDeleted(event);
41
+ default:
42
+ throw new Error(`Unknown group event type: ${eventType}`);
43
+ }
44
+ }
45
+ async ensureBidirectionalFriendship(userId1, userId2, groupId) {
46
+ const user1 = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(userId1);
47
+ const user2 = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(userId2);
48
+ if (!user1 || !user2) {
49
+ console.log(`Cannot create friendship: user ${userId1} or ${userId2} not found`);
50
+ return;
51
+ }
52
+ const existingFriend1to2 = await this.friendModelStore.findByUserIdAndFriendIdAndDeletedIsFalse(userId1, userId2);
53
+ if (!existingFriend1to2) {
54
+ const friendStreamId = `stream-${(0, uuid_1.v4)()}`;
55
+ const friendCreatedEvent = new _1.FriendCreated({
56
+ userId: userId1,
57
+ friendEmail: user2.email,
58
+ friendPhoneNumber: user2.phoneNumber,
59
+ friendDisplayName: user2.displayName,
60
+ friendId: userId2,
61
+ groupId: groupId,
62
+ createdAt: new Date(),
63
+ createdBy: userId1,
64
+ streamId: friendStreamId,
65
+ version: 1,
66
+ });
67
+ await this.friendEventStore.addEvent(userId1, friendCreatedEvent);
68
+ const friendModel = friendCreatedEvent.apply(undefined);
69
+ await this.friendModelStore.save(friendModel);
70
+ }
71
+ const existingFriend2to1 = await this.friendModelStore.findByUserIdAndFriendIdAndDeletedIsFalse(userId2, userId1);
72
+ if (!existingFriend2to1) {
73
+ const friendStreamId = `stream-${(0, uuid_1.v4)()}`;
74
+ const friendCreatedEvent = new _1.FriendCreated({
75
+ userId: userId2,
76
+ friendEmail: user1.email,
77
+ friendPhoneNumber: user1.phoneNumber,
78
+ friendDisplayName: user1.displayName,
79
+ friendId: userId1,
80
+ groupId: groupId,
81
+ createdAt: new Date(),
82
+ createdBy: userId2,
83
+ streamId: friendStreamId,
84
+ version: 1,
85
+ });
86
+ await this.friendEventStore.addEvent(userId2, friendCreatedEvent);
87
+ const friendModel = friendCreatedEvent.apply(undefined);
88
+ await this.friendModelStore.save(friendModel);
89
+ }
90
+ }
91
+ async handleGroupCreated(event) {
92
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
93
+ const updatedModel = event.apply(existingModel);
94
+ await this.modelStore.save(updatedModel);
95
+ const allMemberIds = event.members ?? [];
96
+ const otherMembers = allMemberIds.filter(id => id !== event.userId);
97
+ for (const memberId of otherMembers) {
98
+ const memberUser = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(memberId);
99
+ if (!memberUser) {
100
+ console.log(`Member ${memberId} not found, skipping`);
101
+ continue;
102
+ }
103
+ for (const otherMemberId of allMemberIds) {
104
+ if (memberId !== otherMemberId) {
105
+ await this.ensureBidirectionalFriendship(memberId, otherMemberId, event.groupId);
106
+ }
107
+ }
108
+ const perspectiveGroupStreamId = `stream-${(0, uuid_1.v4)()}`;
109
+ const perspectiveGroupCreated = new _1.GroupCreated({
110
+ userId: memberId,
111
+ groupId: event.groupId,
112
+ name: event.name,
113
+ description: event.description,
114
+ members: event.members,
115
+ createdAt: new Date(),
116
+ createdBy: memberId,
117
+ streamId: perspectiveGroupStreamId,
118
+ version: 1,
119
+ });
120
+ await this.groupEventStore.addEvent(memberId, perspectiveGroupCreated);
121
+ const perspectiveModel = perspectiveGroupCreated.apply(undefined);
122
+ await this.modelStore.save(perspectiveModel);
123
+ }
124
+ if (this.activityEventHandler) {
125
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
126
+ }
127
+ return updatedModel;
128
+ }
129
+ async handleGroupNameChanged(event) {
130
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
131
+ const updatedModel = event.apply(existingModel);
132
+ await this.modelStore.save(updatedModel);
133
+ const allPerspectives = await this.modelStore.findAllByGroupIdAndDeletedIsFalse(updatedModel.groupId);
134
+ for (const perspective of allPerspectives) {
135
+ if (perspective.streamId !== event.streamId) {
136
+ const perspectiveEvent = new _1.GroupNameChanged({
137
+ userId: perspective.userId,
138
+ name: event.name,
139
+ createdAt: new Date(),
140
+ createdBy: event.createdBy,
141
+ streamId: perspective.streamId,
142
+ version: perspective.version + 1,
143
+ });
144
+ await this.groupEventStore.addEvent(perspective.userId, perspectiveEvent);
145
+ const updatedPerspective = perspectiveEvent.apply(perspective);
146
+ await this.modelStore.save(updatedPerspective);
147
+ }
148
+ }
149
+ if (this.activityEventHandler) {
150
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
151
+ }
152
+ return updatedModel;
153
+ }
154
+ async handleGroupDescriptionChanged(event) {
155
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
156
+ const updatedModel = event.apply(existingModel);
157
+ await this.modelStore.save(updatedModel);
158
+ const allPerspectives = await this.modelStore.findAllByGroupIdAndDeletedIsFalse(updatedModel.groupId);
159
+ for (const perspective of allPerspectives) {
160
+ if (perspective.streamId !== event.streamId) {
161
+ const perspectiveEvent = new _1.GroupDescriptionChanged({
162
+ userId: perspective.userId,
163
+ description: event.description,
164
+ createdAt: new Date(),
165
+ createdBy: event.createdBy,
166
+ streamId: perspective.streamId,
167
+ version: perspective.version + 1,
168
+ });
169
+ await this.groupEventStore.addEvent(perspective.userId, perspectiveEvent);
170
+ const updatedPerspective = perspectiveEvent.apply(perspective);
171
+ await this.modelStore.save(updatedPerspective);
172
+ }
173
+ }
174
+ if (this.activityEventHandler) {
175
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
176
+ }
177
+ return updatedModel;
178
+ }
179
+ async handleGroupMembersAdded(event) {
180
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
181
+ if (!existingModel) {
182
+ throw new Error(`Group model not found for streamId ${event.streamId}`);
183
+ }
184
+ const updatedModel = event.apply(existingModel);
185
+ await this.modelStore.save(updatedModel);
186
+ const allMemberIds = updatedModel.members ?? [];
187
+ for (const memberId of event.members) {
188
+ const memberUser = await this.userModelStore.getByStreamIdWhereDeletedIsFalse(memberId);
189
+ if (!memberUser) {
190
+ console.log(`Member ${memberId} not found, skipping`);
191
+ continue;
192
+ }
193
+ for (const otherMemberId of allMemberIds) {
194
+ if (memberId !== otherMemberId) {
195
+ await this.ensureBidirectionalFriendship(memberId, otherMemberId, existingModel.groupId);
196
+ }
197
+ }
198
+ const perspectiveGroupStreamId = `stream-${(0, uuid_1.v4)()}`;
199
+ const perspectiveGroupCreated = new _1.GroupCreated({
200
+ userId: memberId,
201
+ groupId: existingModel.groupId,
202
+ name: existingModel.name,
203
+ description: existingModel.description,
204
+ members: updatedModel.members,
205
+ createdAt: new Date(),
206
+ createdBy: memberId,
207
+ streamId: perspectiveGroupStreamId,
208
+ version: 1,
209
+ });
210
+ await this.groupEventStore.addEvent(memberId, perspectiveGroupCreated);
211
+ const perspectiveModel = perspectiveGroupCreated.apply(undefined);
212
+ await this.modelStore.save(perspectiveModel);
213
+ }
214
+ const allPerspectives = await this.modelStore.findAllByGroupIdAndDeletedIsFalse(updatedModel.groupId);
215
+ for (const perspective of allPerspectives) {
216
+ if (perspective.streamId !== event.streamId && !event.members.includes(perspective.userId)) {
217
+ const perspectiveEvent = new _1.GroupMembersAdded({
218
+ userId: perspective.userId,
219
+ members: event.members,
220
+ createdAt: new Date(),
221
+ createdBy: event.createdBy,
222
+ streamId: perspective.streamId,
223
+ version: perspective.version + 1,
224
+ });
225
+ await this.groupEventStore.addEvent(perspective.userId, perspectiveEvent);
226
+ const updatedPerspective = perspectiveEvent.apply(perspective);
227
+ await this.modelStore.save(updatedPerspective);
228
+ }
229
+ }
230
+ if (this.activityEventHandler) {
231
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
232
+ }
233
+ return updatedModel;
234
+ }
235
+ async handleGroupMembersRemoved(event) {
236
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
237
+ const updatedModel = event.apply(existingModel);
238
+ await this.modelStore.save(updatedModel);
239
+ const allPerspectives = await this.modelStore.findAllByGroupIdAndDeletedIsFalse(updatedModel.groupId);
240
+ for (const perspective of allPerspectives) {
241
+ if (perspective.streamId !== event.streamId) {
242
+ const perspectiveEvent = new _1.GroupMembersRemoved({
243
+ userId: perspective.userId,
244
+ members: event.members,
245
+ createdAt: new Date(),
246
+ createdBy: event.createdBy,
247
+ streamId: perspective.streamId,
248
+ version: perspective.version + 1,
249
+ });
250
+ await this.groupEventStore.addEvent(perspective.userId, perspectiveEvent);
251
+ const updatedPerspective = perspectiveEvent.apply(perspective);
252
+ await this.modelStore.save(updatedPerspective);
253
+ }
254
+ }
255
+ if (this.activityEventHandler) {
256
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
257
+ }
258
+ return updatedModel;
259
+ }
260
+ async handleGroupDeleted(event) {
261
+ const existingModel = await this.modelStore.getByStreamIdWhereDeletedIsFalse(event.streamId);
262
+ const updatedModel = event.apply(existingModel);
263
+ await this.modelStore.save(updatedModel);
264
+ if (this.activityEventHandler) {
265
+ await this.activityEventHandler.createActivityLog(event, existingModel, updatedModel);
266
+ }
267
+ return updatedModel;
268
+ }
269
+ }
270
+ exports.GroupEventHandler = GroupEventHandler;
@@ -0,0 +1,25 @@
1
+ import { GroupTransactionCreated, GroupTransactionSplitDetailsChanged, GroupTransactionModel, Event } from '.';
2
+ import { GroupTransactionModelStore } from '.';
3
+ import { GroupTransactionEventStore } from '.';
4
+ import { GroupModelStore } from '.';
5
+ import { TransactionEventStore } from '.';
6
+ import { TransactionModelStore } from '.';
7
+ import { ActivityEventHandler } from './ActivityEventHandler';
8
+ export declare class GroupTransactionEventHandler {
9
+ private modelStore;
10
+ private eventStore;
11
+ private groupModelStore;
12
+ private transactionEventStore;
13
+ private transactionModelStore;
14
+ private activityEventHandler?;
15
+ constructor(modelStore: GroupTransactionModelStore, eventStore: GroupTransactionEventStore, groupModelStore: GroupModelStore, transactionEventStore: TransactionEventStore, transactionModelStore: TransactionModelStore, activityEventHandler?: ActivityEventHandler | undefined);
16
+ handleEvent(event: Event): Promise<GroupTransactionModel>;
17
+ private calculateNetBalances;
18
+ private createFriendTransactions;
19
+ private updateFriendTransactions;
20
+ private calculateRequiredTransactions;
21
+ private updateExistingFriendTransactions;
22
+ handleGroupTransactionCreated(event: GroupTransactionCreated): Promise<GroupTransactionModel>;
23
+ handleGroupTransactionSplitDetailsChanged(event: GroupTransactionSplitDetailsChanged): Promise<GroupTransactionModel>;
24
+ }
25
+ //# sourceMappingURL=GroupTransactionEventHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupTransactionEventHandler.d.ts","sourceRoot":"","sources":["../src/GroupTransactionEventHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EACvB,mCAAmC,EACnC,qBAAqB,EAIrB,KAAK,EAGR,MAAM,GAAG,CAAC;AACX,OAAO,EAAC,0BAA0B,EAAC,MAAM,GAAG,CAAC;AAC7C,OAAO,EAAC,0BAA0B,EAAC,MAAM,GAAG,CAAC;AAC7C,OAAO,EAAC,eAAe,EAAC,MAAM,GAAG,CAAC;AAClC,OAAO,EAAC,qBAAqB,EAAC,MAAM,GAAG,CAAC;AACxC,OAAO,EAAC,qBAAqB,EAAC,MAAM,GAAG,CAAC;AACxC,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAI5D,qBAAa,4BAA4B;IAEjC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,qBAAqB;IAC7B,OAAO,CAAC,qBAAqB;IAC7B,OAAO,CAAC,oBAAoB,CAAC;gBALrB,UAAU,EAAE,0BAA0B,EACtC,UAAU,EAAE,0BAA0B,EACtC,eAAe,EAAE,eAAe,EAChC,qBAAqB,EAAE,qBAAqB,EAC5C,qBAAqB,EAAE,qBAAqB,EAC5C,oBAAoB,CAAC,EAAE,oBAAoB,YAAA;IAGjD,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAqB/D,OAAO,CAAC,oBAAoB;YAWd,wBAAwB;YA0ExB,wBAAwB;IAStC,OAAO,CAAC,6BAA6B;YA6CvB,gCAAgC;IAiFxC,6BAA6B,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA8C7F,yCAAyC,CAAC,KAAK,EAAE,mCAAmC,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAoD9H"}