@messenger-box/platform-server 10.0.3-alpha.7 → 10.0.3-alpha.72

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 (149) hide show
  1. package/lib/containers/containers.js +4 -1
  2. package/lib/containers/containers.js.map +1 -1
  3. package/lib/containers/context-services-from-container.d.ts +1 -1
  4. package/lib/containers/context-services-from-container.js +1 -1
  5. package/lib/containers/context-services-from-container.js.map +1 -1
  6. package/lib/graphql/resolvers/channel-member.d.ts +3 -2
  7. package/lib/graphql/resolvers/channel-member.js +30 -5
  8. package/lib/graphql/resolvers/channel-member.js.map +1 -1
  9. package/lib/graphql/resolvers/channel.d.ts +3 -2
  10. package/lib/graphql/resolvers/channel.js +279 -53
  11. package/lib/graphql/resolvers/channel.js.map +1 -1
  12. package/lib/graphql/resolvers/extended-token-account.d.ts +3 -2
  13. package/lib/graphql/resolvers/extended-token-account.js +90 -23
  14. package/lib/graphql/resolvers/extended-token-account.js.map +1 -1
  15. package/lib/graphql/resolvers/index.d.ts +1 -1
  16. package/lib/graphql/resolvers/post-thread.d.ts +1 -1
  17. package/lib/graphql/resolvers/post-thread.js +294 -132
  18. package/lib/graphql/resolvers/post-thread.js.map +1 -1
  19. package/lib/graphql/resolvers/post.d.ts +2 -3
  20. package/lib/graphql/resolvers/post.js +696 -234
  21. package/lib/graphql/resolvers/post.js.map +1 -1
  22. package/lib/graphql/resolvers/reaction.d.ts +3 -2
  23. package/lib/graphql/resolvers/reaction.js +96 -14
  24. package/lib/graphql/resolvers/reaction.js.map +1 -1
  25. package/lib/graphql/schema/channel-member.graphql +110 -21
  26. package/lib/graphql/schema/channel-member.graphql.js +1 -1
  27. package/lib/graphql/schema/channel.graphql +337 -38
  28. package/lib/graphql/schema/channel.graphql.js +1 -1
  29. package/lib/graphql/schema/post-thread.graphql +167 -21
  30. package/lib/graphql/schema/post-thread.graphql.js +1 -1
  31. package/lib/graphql/schema/post.graphql +284 -40
  32. package/lib/graphql/schema/post.graphql.js +1 -1
  33. package/lib/graphql/schema/reaction.graphql +71 -13
  34. package/lib/graphql/schema/reaction.graphql.js +1 -1
  35. package/lib/graphql/schema/services.graphql +2 -0
  36. package/lib/graphql/schema/users.graphql +76 -13
  37. package/lib/graphql/schema/users.graphql.js +1 -1
  38. package/lib/index.js +1 -1
  39. package/lib/index.js.map +1 -1
  40. package/lib/interfaces/index.d.ts +0 -1
  41. package/lib/interfaces/services.d.ts +1 -1
  42. package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.d.ts +17 -0
  43. package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.js +44 -0
  44. package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.js.map +1 -0
  45. package/lib/migrations/dbMigrations/index.d.ts +1 -0
  46. package/lib/migrations/index.d.ts +1 -0
  47. package/lib/migrations/mail-template-migration.js +1 -1
  48. package/lib/migrations/message-notification-template-migration.d.ts +1 -1
  49. package/lib/migrations/message-notification-template-migration.js +1 -1
  50. package/lib/plugins/channel-moleculer-service.d.ts +21 -1
  51. package/lib/plugins/channel-moleculer-service.js +417 -115
  52. package/lib/plugins/channel-moleculer-service.js.map +1 -1
  53. package/lib/plugins/extended-token-account-moleculer-service.d.ts +25 -1
  54. package/lib/plugins/extended-token-account-moleculer-service.js +348 -22
  55. package/lib/plugins/extended-token-account-moleculer-service.js.map +1 -1
  56. package/lib/plugins/messenger-notification-moleculer-service.d.ts +27 -3
  57. package/lib/plugins/messenger-notification-moleculer-service.js +404 -58
  58. package/lib/plugins/messenger-notification-moleculer-service.js.map +1 -1
  59. package/lib/plugins/post-moleculer-service.d.ts +85 -21
  60. package/lib/plugins/post-moleculer-service.js +986 -256
  61. package/lib/plugins/post-moleculer-service.js.map +1 -1
  62. package/lib/plugins/post-thread-moleculer-service.d.ts +33 -1
  63. package/lib/plugins/post-thread-moleculer-service.js +326 -8
  64. package/lib/plugins/post-thread-moleculer-service.js.map +1 -1
  65. package/lib/plugins/reaction-moleculer-service.js +1 -1
  66. package/lib/plugins/reaction-moleculer-service.js.map +1 -1
  67. package/lib/preferences/settings/post-settings.d.ts +2 -0
  68. package/lib/preferences/settings/post-settings.js +47 -9
  69. package/lib/preferences/settings/post-settings.js.map +1 -1
  70. package/lib/services/channel-service.d.ts +179 -33
  71. package/lib/services/channel-service.js +821 -274
  72. package/lib/services/channel-service.js.map +1 -1
  73. package/lib/services/extended-token-account-service.d.ts +130 -14
  74. package/lib/services/extended-token-account-service.js +462 -52
  75. package/lib/services/extended-token-account-service.js.map +1 -1
  76. package/lib/services/index.d.ts +1 -0
  77. package/lib/services/messenger-notification-service.d.ts +106 -13
  78. package/lib/services/messenger-notification-service.js +824 -442
  79. package/lib/services/messenger-notification-service.js.map +1 -1
  80. package/lib/services/post-service.d.ts +182 -16
  81. package/lib/services/post-service.js +731 -115
  82. package/lib/services/post-service.js.map +1 -1
  83. package/lib/services/post-thread-service.d.ts +114 -5
  84. package/lib/services/post-thread-service.js +400 -13
  85. package/lib/services/post-thread-service.js.map +1 -1
  86. package/lib/services/proxy-services/channel-microservice.d.ts +5 -3
  87. package/lib/services/proxy-services/channel-microservice.js +19 -10
  88. package/lib/services/proxy-services/channel-microservice.js.map +1 -1
  89. package/lib/services/proxy-services/messenger-notification-microservice.d.ts +128 -8
  90. package/lib/services/proxy-services/messenger-notification-microservice.js +324 -29
  91. package/lib/services/proxy-services/messenger-notification-microservice.js.map +1 -1
  92. package/lib/services/proxy-services/post-microservice.d.ts +186 -12
  93. package/lib/services/proxy-services/post-microservice.js +543 -54
  94. package/lib/services/proxy-services/post-microservice.js.map +1 -1
  95. package/lib/services/proxy-services/post-thread-microservice.d.ts +134 -3
  96. package/lib/services/proxy-services/post-thread-microservice.js +388 -6
  97. package/lib/services/proxy-services/post-thread-microservice.js.map +1 -1
  98. package/lib/services/proxy-services/reaction-microservice.d.ts +161 -3
  99. package/lib/services/proxy-services/reaction-microservice.js +474 -2
  100. package/lib/services/proxy-services/reaction-microservice.js.map +1 -1
  101. package/lib/services/reaction-service.d.ts +124 -4
  102. package/lib/services/reaction-service.js +415 -3
  103. package/lib/services/reaction-service.js.map +1 -1
  104. package/lib/services/redis-cache-manager.d.ts +18 -0
  105. package/lib/services/redis-cache-manager.js +83 -0
  106. package/lib/services/redis-cache-manager.js.map +1 -0
  107. package/lib/store/models/account-token-store.d.ts +1 -1
  108. package/lib/store/models/account-token-store.js.map +1 -1
  109. package/lib/store/models/channel.d.ts +2 -3
  110. package/lib/store/models/channel.js +181 -72
  111. package/lib/store/models/channel.js.map +1 -1
  112. package/lib/store/models/post-thread.d.ts +3 -3
  113. package/lib/store/models/post-thread.js +96 -14
  114. package/lib/store/models/post-thread.js.map +1 -1
  115. package/lib/store/models/post.d.ts +2 -3
  116. package/lib/store/models/post.js +143 -23
  117. package/lib/store/models/post.js.map +1 -1
  118. package/lib/store/models/reaction.d.ts +2 -3
  119. package/lib/store/models/reaction.js +67 -8
  120. package/lib/store/models/reaction.js.map +1 -1
  121. package/lib/store/repositories/__tests__/__fixtures__/team-repository.d.ts +3 -3
  122. package/lib/store/repositories/channel-repository.d.ts +6 -6
  123. package/lib/store/repositories/channel-repository.js +5 -2
  124. package/lib/store/repositories/channel-repository.js.map +1 -1
  125. package/lib/store/repositories/post-repository.d.ts +6 -6
  126. package/lib/store/repositories/post-repository.js +5 -2
  127. package/lib/store/repositories/post-repository.js.map +1 -1
  128. package/lib/store/repositories/post-thread-repository.d.ts +6 -6
  129. package/lib/store/repositories/post-thread-repository.js +5 -2
  130. package/lib/store/repositories/post-thread-repository.js.map +1 -1
  131. package/lib/store/repositories/reaction-repository.d.ts +6 -6
  132. package/lib/store/repositories/reaction-repository.js +5 -2
  133. package/lib/store/repositories/reaction-repository.js.map +1 -1
  134. package/lib/templates/constants/SERVER_TYPES.ts.template +0 -3
  135. package/lib/templates/repositories/ChannelRepository.ts.template +3 -3
  136. package/lib/templates/repositories/PostRepository.ts.template +3 -3
  137. package/lib/templates/repositories/PostThreadRepository.ts.template +3 -3
  138. package/lib/templates/repositories/ReactionRepository.ts.template +3 -4
  139. package/lib/templates/services/ChannelService.ts.template +280 -39
  140. package/lib/templates/services/ExtendedTokenAccountService.ts.template +104 -9
  141. package/lib/templates/services/MessengerNotificationService.ts.template +94 -19
  142. package/lib/templates/services/PostService.ts.template +184 -20
  143. package/lib/templates/services/PostThreadService.ts.template +151 -6
  144. package/lib/templates/services/ReactionService.ts.template +129 -3
  145. package/lib/templates/services/RedisCacheManager.ts.template +22 -0
  146. package/package.json +6 -5
  147. package/lib/interfaces/context.d.ts +0 -14
  148. package/lib/store/models/common-options.js +0 -20
  149. package/lib/store/models/common-options.js.map +0 -1
@@ -1,14 +1,46 @@
1
- import {Service}from'moleculer';import {MoleculerTopics,SERVER_TYPES}from'common';import {ApolloClientMixin}from'@adminide-stack/platform-server';import {BaseServiceMixin}from'@common-stack/store-mongo';import uniqBy from'lodash/uniqBy.js';import {config}from'../config/env-config.js';// import { TYPES } from '../constants';
2
- // import { IPostService, IPostServiceInput } from '../interfaces';
1
+ import {Service}from'moleculer';import {MoleculerTopics,SERVER_TYPES}from'common/server';import {ApolloClientMixin}from'@adminide-stack/platform-server';import {BaseServiceMixin}from'@common-stack/store-mongo';import uniqBy from'lodash/uniqBy';import {logger}from'@common-stack/server-core';import {config}from'../config/env-config.js';/**
2
+ * Post Moleculer Service
3
+ * ----------------------
4
+ *
5
+ * This Moleculer service provides comprehensive post management capabilities within
6
+ * the messenger platform ecosystem. It acts as a distributed service layer for
7
+ * handling post creation, file attachments, message threading, real-time notifications,
8
+ * and cross-service communication.
9
+ *
10
+ * Key capabilities:
11
+ * - Post lifecycle management with threading support
12
+ * - File attachment and upload link generation
13
+ * - Real-time message delivery and read receipts
14
+ * - Post thread creation and management
15
+ * - Channel integration and message counting
16
+ * - Event-driven architecture for real-time updates
17
+ * - Distributed service communication via Moleculer
18
+ * - Comprehensive error handling and logging
19
+ *
20
+ * The service integrates with multiple platform components including channels,
21
+ * notifications, file management, and real-time publishing systems to provide
22
+ * a cohesive messaging experience across the platform.
23
+ */
24
+ /**
25
+ * PostMoleculerService Class
26
+ *
27
+ * Comprehensive Moleculer service for distributed post management operations.
28
+ * Provides event-driven architecture, real-time communication, and seamless
29
+ * integration with other platform services.
30
+ */
3
31
  class PostMoleculerService extends Service {
4
32
  postService;
33
+ container;
5
34
  constructor(broker, {
6
- container
35
+ container,
36
+ settings
7
37
  }) {
8
38
  super(broker);
39
+ this.container = container;
9
40
  const topic = MoleculerTopics.PostService;
10
41
  this.postService = container.get(SERVER_TYPES.PostService);
11
42
  this.pubsub = container.get('PubSub');
43
+ logger.info(`Initializing PostMoleculerService with topic: ${topic}`);
12
44
  this.parseServiceSchema({
13
45
  name: topic,
14
46
  mixins: [ApolloClientMixin, BaseServiceMixin(this.postService)],
@@ -17,113 +49,331 @@ class PostMoleculerService extends Service {
17
49
  serverUri: config.GRAPHQL_URL
18
50
  }
19
51
  },
20
- events: {
52
+ actions: {
53
+ create: {
54
+ params: {
55
+ data: {
56
+ type: 'object'
57
+ }
58
+ },
59
+ async handler(ctx) {
60
+ try {
61
+ logger.debug('Creating post via Moleculer service', {
62
+ data: ctx.params.data,
63
+ nodeId: this.broker.nodeID,
64
+ serviceId: this.name
65
+ });
66
+ if (!this.postService) {
67
+ throw new Error('PostService is not initialized');
68
+ }
69
+ const result = await this.postService.create(ctx.params.data);
70
+ if (result instanceof Error) {
71
+ logger.error('Error creating post: %o', {
72
+ error: result,
73
+ data: ctx.params.data,
74
+ nodeId: this.broker.nodeID,
75
+ serviceId: this.name
76
+ });
77
+ throw result;
78
+ }
79
+ if (!result || !result.id) {
80
+ throw new Error('Post creation failed - invalid result returned');
81
+ }
82
+ logger.debug('Post created successfully', {
83
+ postId: result.id,
84
+ nodeId: this.broker.nodeID,
85
+ serviceId: this.name
86
+ });
87
+ return result;
88
+ } catch (error) {
89
+ logger.error('Error in create action: %o', {
90
+ error,
91
+ data: ctx.params.data,
92
+ nodeId: this.broker.nodeID,
93
+ serviceId: this.name,
94
+ stack: error.stack
95
+ });
96
+ throw error;
97
+ }
98
+ }
99
+ },
100
+ /**
101
+ * Handles post thread creation events
102
+ * Publishes real-time updates for thread creation
103
+ */
21
104
  onCreatePostThread: {
22
105
  handler: async ctx => {
23
- const {
24
- post,
25
- postThread
26
- } = ctx.params;
27
- const {
28
- channel: channelId,
29
- parentId: postParentId
30
- } = post;
31
- const triggerName = `THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}`;
32
- const triggerPostThreadName = postParentId ? `THREAD_POST_CREATED_${channelId}_${postParentId}` : `POST_CREATED.${channelId}`;
33
- await Promise.all([this.pubsub.publish(triggerName, {
34
- isCreated: true,
35
- isUpdated: false,
36
- lastMessage: post,
37
- data: postThread
38
- }), this.pubsub.publish(triggerPostThreadName, post), this.pubsub.publish(`THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}${postParentId ? `_${postParentId}` : ''}`, {
39
- isCreated: true,
40
- isUpdated: false,
41
- lastMessage: post,
42
- data: postThread
43
- })]);
106
+ try {
107
+ logger.debug('Processing post thread creation event', {
108
+ postId: ctx.params.post?.id,
109
+ threadId: ctx.params.postThread?.id,
110
+ channelId: ctx.params.post?.channel
111
+ });
112
+ const {
113
+ post,
114
+ postThread
115
+ } = ctx.params;
116
+ const {
117
+ channel: channelId,
118
+ parentId: postParentId
119
+ } = post;
120
+ const triggerName = `THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}`;
121
+ const triggerPostThreadName = postParentId ? `THREAD_POST_CREATED_${channelId}_${postParentId}` : `POST_CREATED.${channelId}`;
122
+ const publishPromises = [this.pubsub.publish(triggerName, {
123
+ isCreated: true,
124
+ isUpdated: false,
125
+ lastMessage: post,
126
+ data: postThread
127
+ }), this.pubsub.publish(triggerPostThreadName, post), this.pubsub.publish(`THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}${postParentId ? `_${postParentId}` : ''}`, {
128
+ isCreated: true,
129
+ isUpdated: false,
130
+ lastMessage: post,
131
+ data: postThread
132
+ })];
133
+ await Promise.all(publishPromises);
134
+ logger.debug('Post thread creation event processed successfully', {
135
+ postId: post?.id,
136
+ threadId: postThread?.id,
137
+ publishedEvents: publishPromises.length
138
+ });
139
+ } catch (error) {
140
+ logger.error('Error processing post thread creation event: %o', error);
141
+ throw error;
142
+ }
44
143
  }
45
144
  },
145
+ /**
146
+ * Handles post thread update events
147
+ * Updates thread participants and publishes real-time updates
148
+ */
46
149
  onUpdatePostThread: {
47
150
  handler: async ctx => {
48
- const {
49
- post,
50
- postThread,
51
- accountId,
52
- role,
53
- orgId
54
- } = ctx.params;
55
- const defaultResponder = [{
56
- user: accountId,
57
- roles: role,
58
- orgName: orgId
59
- }];
60
- const normalizedParticipants = [...postThread?.participants, ...defaultResponder].map(i => ({
61
- ...i,
62
- user: i.user.toString()
63
- }));
64
- const participants = uniqBy(normalizedParticipants, 'user');
65
- await this.broker.call(`${MoleculerTopics.PostThreadService}.update`, {
66
- id: postThread.id,
67
- data: {
68
- replyCount: postThread.replyCount + 1,
69
- lastReplyAt: post.createdAt,
70
- updatedAt: post.createdAt,
71
- participants
151
+ try {
152
+ logger.debug('Processing post thread update event', {
153
+ postId: ctx.params.post?.id,
154
+ threadId: ctx.params.postThread?.id,
155
+ accountId: ctx.params.accountId,
156
+ orgId: ctx.params.orgId
157
+ });
158
+ const {
159
+ post,
160
+ postThread,
161
+ accountId,
162
+ role,
163
+ orgId
164
+ } = ctx.params;
165
+ // Build participant list
166
+ const defaultResponder = [{
167
+ user: accountId,
168
+ roles: role,
169
+ orgName: orgId
170
+ }];
171
+ const normalizedParticipants = [...(postThread?.participants || []), ...defaultResponder].map(i => ({
172
+ ...i,
173
+ user: i.user.toString()
174
+ }));
175
+ const participants = uniqBy(normalizedParticipants, 'user');
176
+ // Update post thread
177
+ await this.broker.call(`${MoleculerTopics.PostThreadService}.update`, {
178
+ id: postThread.id,
179
+ data: {
180
+ replyCount: postThread.replyCount + 1,
181
+ lastReplyAt: post.createdAt,
182
+ updatedAt: post.createdAt,
183
+ participants
184
+ }
185
+ });
186
+ // Prepare trigger payload
187
+ const triggerPayload = {
188
+ isCreated: false,
189
+ isUpdated: true,
190
+ lastMessage: post,
191
+ data: postThread ? {
192
+ ...postThread,
193
+ replyCount: postThread.replyCount + 1,
194
+ lastReplyAt: post.createdAt,
195
+ updatedAt: post.createdAt,
196
+ participants
197
+ } : {}
198
+ };
199
+ const {
200
+ channel: channelId,
201
+ parentId: postParentId
202
+ } = post;
203
+ const triggerName = `THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}`;
204
+ const triggerPostThreadName = `THREAD_POST_CREATED_${channelId}_${postParentId}`;
205
+ // Publish updates
206
+ await Promise.all([this.pubsub.publish(triggerName, triggerPayload), this.pubsub.publish(triggerPostThreadName, post), this.pubsub.publish(`${triggerName}${postParentId ? `_${postParentId}` : ''}`, triggerPayload)]);
207
+ logger.debug('Post thread update event processed successfully', {
208
+ postId: post?.id,
209
+ threadId: postThread?.id,
210
+ participantCount: participants.length
211
+ });
212
+ } catch (error) {
213
+ logger.error('Error processing post thread update event: %o', error);
214
+ throw error;
215
+ }
216
+ }
217
+ },
218
+ /**
219
+ * Handles post creation events
220
+ * Triggers real-time notifications and channel updates
221
+ */
222
+ onPostCreated: {
223
+ handler: async ctx => {
224
+ try {
225
+ logger.debug('Processing post creation event', {
226
+ postId: ctx.params.post?.id,
227
+ channelId: ctx.params.post?.channel,
228
+ authorId: ctx.params.post?.author
229
+ });
230
+ const {
231
+ post,
232
+ userContext
233
+ } = ctx.params;
234
+ // Emit channel update event
235
+ await this.broker.emit('onChannelUpdated', {
236
+ channelId: post.channel,
237
+ lastPostId: post.id,
238
+ lastPostAt: post.createdAt,
239
+ userContext
240
+ });
241
+ logger.debug('Post creation event processed successfully', {
242
+ postId: post?.id,
243
+ channelId: post?.channel
244
+ });
245
+ } catch (error) {
246
+ logger.error('Error processing post creation event: %o', error);
247
+ // Don't throw to prevent breaking post creation
248
+ }
249
+ }
250
+ },
251
+ /**
252
+ * Handles bulk post processing events
253
+ * Processes multiple posts in batch operations
254
+ */
255
+ onBulkPostProcess: {
256
+ handler: async ctx => {
257
+ try {
258
+ logger.debug('Processing bulk post operation', {
259
+ postCount: ctx.params.posts?.length,
260
+ operation: ctx.params.operation
261
+ });
262
+ const {
263
+ posts,
264
+ operation,
265
+ userContext
266
+ } = ctx.params;
267
+ for (const post of posts) {
268
+ switch (operation) {
269
+ case 'delete':
270
+ // Use the base service delete method
271
+ await this.postService.delete({
272
+ id: post.id
273
+ });
274
+ break;
275
+ case 'archive':
276
+ // Implementation for archiving posts
277
+ break;
278
+ default:
279
+ logger.warn('Unknown bulk operation', {
280
+ operation
281
+ });
282
+ }
72
283
  }
73
- });
74
- const triggerPayload = {
75
- isCreated: false,
76
- isUpdated: true,
77
- lastMessage: post,
78
- data: postThread ? {
79
- ...postThread,
80
- replyCount: postThread.replyCount + 1,
81
- lastReplyAt: post.createdAt,
82
- updatedAt: post.createdAt,
83
- participants
84
- } : {}
85
- };
86
- const {
87
- channel: channelId,
88
- parentId: postParentId
89
- } = post;
90
- const triggerName = `THREAD_CREATED_UPDATED${channelId ? `_${channelId}` : ''}`;
91
- const triggerPostThreadName = `THREAD_POST_CREATED_${channelId}_${postParentId}`;
92
- await Promise.all([this.pubsub.publish(triggerName, triggerPayload), this.pubsub.publish(triggerPostThreadName, post), this.pubsub.publish(`${triggerName}${postParentId ? `_${postParentId}` : ''}`, triggerPayload)]);
284
+ logger.debug('Bulk post operation completed', {
285
+ postCount: posts.length,
286
+ operation
287
+ });
288
+ } catch (error) {
289
+ logger.error('Error processing bulk post operation: %o', error);
290
+ throw error;
291
+ }
93
292
  }
94
- }
95
- },
96
- actions: {
293
+ },
97
294
  attachUploadedFile: {
98
295
  params: {
99
296
  postId: 'string',
100
297
  createdBy: 'string',
101
298
  file: 'object'
102
299
  },
103
- handler(ctx) {
104
- const {
105
- postId,
106
- createdBy,
107
- file
108
- } = ctx.params;
109
- return this.postService.attachUploadedFile(postId, file, createdBy);
300
+ async handler(ctx) {
301
+ try {
302
+ logger.debug('Attaching uploaded file to post', {
303
+ postId: ctx.params.postId,
304
+ createdBy: ctx.params.createdBy,
305
+ fileName: ctx.params.file?.name
306
+ });
307
+ const {
308
+ postId,
309
+ createdBy,
310
+ file
311
+ } = ctx.params;
312
+ const result = await this.postService.attachUploadedFile(postId, file, createdBy);
313
+ if (result instanceof Error) {
314
+ logger.error('Failed to attach uploaded file', {
315
+ postId,
316
+ error: result.message
317
+ });
318
+ throw result;
319
+ }
320
+ logger.debug('File attached successfully', {
321
+ postId,
322
+ fileId: result?.id,
323
+ createdBy
324
+ });
325
+ return result;
326
+ } catch (error) {
327
+ logger.error('Error in attachUploadedFile action: %o', error);
328
+ throw error;
329
+ }
110
330
  }
111
331
  },
332
+ /**
333
+ * Creates a file upload link for a post
334
+ */
112
335
  createFileUploadLink: {
113
336
  params: {
114
337
  postId: 'string',
115
338
  filename: 'string',
116
339
  userId: 'string'
117
340
  },
118
- handler(ctx) {
119
- const {
120
- postId,
121
- filename,
122
- userId
123
- } = ctx.params;
124
- return this.postService.createFileUploadLink(postId, filename, userId);
341
+ async handler(ctx) {
342
+ try {
343
+ logger.debug('Creating file upload link', {
344
+ postId: ctx.params.postId,
345
+ filename: ctx.params.filename,
346
+ userId: ctx.params.userId
347
+ });
348
+ const {
349
+ postId,
350
+ filename,
351
+ userId
352
+ } = ctx.params;
353
+ const result = await this.postService.createFileUploadLink(postId, filename, userId);
354
+ if (result instanceof Error) {
355
+ logger.error('Failed to create file upload link', {
356
+ postId,
357
+ filename,
358
+ error: result.message
359
+ });
360
+ throw result;
361
+ }
362
+ logger.debug('File upload link created successfully', {
363
+ postId,
364
+ filename,
365
+ userId
366
+ });
367
+ return result;
368
+ } catch (error) {
369
+ logger.error('Error in createFileUploadLink action: %o', error);
370
+ throw error;
371
+ }
125
372
  }
126
373
  },
374
+ /**
375
+ * Attaches multiple uploaded files to a post
376
+ */
127
377
  attachUploadedFiles: {
128
378
  params: {
129
379
  postId: 'string',
@@ -133,15 +383,41 @@ class PostMoleculerService extends Service {
133
383
  items: 'object'
134
384
  }
135
385
  },
136
- handler(ctx) {
137
- const {
138
- postId,
139
- createdBy,
140
- files
141
- } = ctx.params;
142
- return this.postService.attachUploadedFiles(postId, files, createdBy);
386
+ async handler(ctx) {
387
+ try {
388
+ logger.debug('Attaching multiple uploaded files to post', {
389
+ postId: ctx.params.postId,
390
+ createdBy: ctx.params.createdBy,
391
+ fileCount: ctx.params.files?.length
392
+ });
393
+ const {
394
+ postId,
395
+ createdBy,
396
+ files
397
+ } = ctx.params;
398
+ const result = await this.postService.attachUploadedFiles(postId, files, createdBy);
399
+ if (result instanceof Error) {
400
+ logger.error('Failed to attach uploaded files', {
401
+ postId,
402
+ error: result.message
403
+ });
404
+ throw result;
405
+ }
406
+ logger.debug('Files attached successfully', {
407
+ postId,
408
+ fileCount: result?.length,
409
+ createdBy
410
+ });
411
+ return result;
412
+ } catch (error) {
413
+ logger.error('Error in attachUploadedFiles action: %o', error);
414
+ throw error;
415
+ }
143
416
  }
144
417
  },
418
+ /**
419
+ * Creates upload links for multiple files
420
+ */
145
421
  createFilesUploadLink: {
146
422
  params: {
147
423
  postId: 'string',
@@ -151,110 +427,469 @@ class PostMoleculerService extends Service {
151
427
  },
152
428
  userId: 'string'
153
429
  },
154
- handler(ctx) {
155
- const {
156
- postId,
157
- filenames,
158
- userId
159
- } = ctx.params;
160
- return this.postService.createFilesUploadLink(postId, filenames, userId);
430
+ async handler(ctx) {
431
+ try {
432
+ logger.debug('Creating multiple file upload links', {
433
+ postId: ctx.params.postId,
434
+ fileCount: ctx.params.filenames?.length,
435
+ userId: ctx.params.userId
436
+ });
437
+ const {
438
+ postId,
439
+ filenames,
440
+ userId
441
+ } = ctx.params;
442
+ const result = await this.postService.createFilesUploadLink(postId, filenames, userId);
443
+ if (result instanceof Error) {
444
+ logger.error('Failed to create file upload links', {
445
+ postId,
446
+ error: result.message
447
+ });
448
+ throw result;
449
+ }
450
+ logger.debug('File upload links created successfully', {
451
+ postId,
452
+ linkCount: result?.length,
453
+ userId
454
+ });
455
+ return result;
456
+ } catch (error) {
457
+ logger.error('Error in createFilesUploadLink action: %o', error);
458
+ throw error;
459
+ }
161
460
  }
162
461
  },
462
+ /**
463
+ * Deletes a file by URL
464
+ */
163
465
  deleteFile: {
164
466
  params: {
165
467
  url: 'string'
166
468
  },
167
- handler(ctx) {
168
- const {
169
- url
170
- } = ctx.params;
171
- return this.postService.deleteFile(url);
469
+ async handler(ctx) {
470
+ try {
471
+ logger.debug('Deleting file', {
472
+ url: ctx.params.url
473
+ });
474
+ const {
475
+ url
476
+ } = ctx.params;
477
+ const result = await this.postService.deleteFile(url);
478
+ if (result instanceof Error) {
479
+ logger.error('Failed to delete file', {
480
+ url,
481
+ error: result.message
482
+ });
483
+ throw result;
484
+ }
485
+ logger.debug('File deleted successfully', {
486
+ url,
487
+ success: result
488
+ });
489
+ return result;
490
+ } catch (error) {
491
+ logger.error('Error in deleteFile action: %o', error);
492
+ throw error;
493
+ }
172
494
  }
173
495
  },
496
+ /**
497
+ * Marks a message as read
498
+ */
174
499
  readMessage: {
175
500
  params: {
176
501
  channelId: 'string',
177
502
  messageId: 'string',
178
503
  user: 'string'
179
504
  },
180
- handler(ctx) {
181
- const {
182
- user,
183
- ...rest
184
- } = ctx.params;
185
- return this.postService.readMessage(rest, user);
505
+ async handler(ctx) {
506
+ try {
507
+ logger.debug('Marking message as read', {
508
+ channelId: ctx.params.channelId,
509
+ messageId: ctx.params.messageId,
510
+ userId: ctx.params.user
511
+ });
512
+ const {
513
+ user,
514
+ ...rest
515
+ } = ctx.params;
516
+ const result = await this.postService.readMessage(rest, user);
517
+ if (result instanceof Error) {
518
+ logger.error('Failed to mark message as read', {
519
+ messageId: rest.messageId,
520
+ error: result.message
521
+ });
522
+ throw result;
523
+ }
524
+ logger.debug('Message marked as read successfully', {
525
+ messageId: rest.messageId,
526
+ userId: user
527
+ });
528
+ return result;
529
+ } catch (error) {
530
+ logger.error('Error in readMessage action: %o', error);
531
+ throw error;
532
+ }
186
533
  }
187
534
  },
535
+ /**
536
+ * Marks a message as delivered
537
+ */
188
538
  deliverMessage: {
189
539
  params: {
190
540
  channelId: 'string',
191
541
  messageId: 'string',
192
542
  user: 'string'
193
543
  },
194
- handler(ctx) {
195
- const {
196
- user,
197
- ...rest
198
- } = ctx.params;
199
- return this.postService.deliverMessage(rest, user);
544
+ async handler(ctx) {
545
+ try {
546
+ logger.debug('Marking message as delivered', {
547
+ channelId: ctx.params.channelId,
548
+ messageId: ctx.params.messageId,
549
+ userId: ctx.params.user
550
+ });
551
+ const {
552
+ user,
553
+ ...rest
554
+ } = ctx.params;
555
+ const result = await this.postService.deliverMessage(rest, user);
556
+ if (result instanceof Error) {
557
+ logger.error('Failed to mark message as delivered', {
558
+ messageId: rest.messageId,
559
+ error: result.message
560
+ });
561
+ throw result;
562
+ }
563
+ logger.debug('Message marked as delivered successfully', {
564
+ messageId: rest.messageId,
565
+ userId: user
566
+ });
567
+ return result;
568
+ } catch (error) {
569
+ logger.error('Error in deliverMessage action: %o', error);
570
+ throw error;
571
+ }
200
572
  }
201
573
  },
574
+ /**
575
+ * Creates a post without subscription/real-time publishing
576
+ */
202
577
  createWithoutSubscription: {
203
578
  params: {
204
579
  data: 'object'
205
580
  },
206
581
  async handler(ctx) {
207
- const {
208
- data
209
- } = ctx.params;
210
- return this.postService.createWithoutSubscription(data);
582
+ try {
583
+ logger.debug('Creating post without subscription', {
584
+ channelId: ctx.params.data?.channel,
585
+ authorId: ctx.params.data?.author
586
+ });
587
+ const {
588
+ data
589
+ } = ctx.params;
590
+ const result = await this.postService.createWithoutSubscription(data);
591
+ if (result instanceof Error) {
592
+ logger.error('Failed to create post without subscription', {
593
+ error: result.message
594
+ });
595
+ throw result;
596
+ }
597
+ logger.debug('Post created successfully without subscription', {
598
+ postId: result?.id,
599
+ channelId: data?.channel
600
+ });
601
+ return result;
602
+ } catch (error) {
603
+ logger.error('Error in createWithoutSubscription action: %o', error);
604
+ throw error;
605
+ }
211
606
  }
212
607
  },
608
+ /**
609
+ * Creates a post with associated post thread
610
+ */
213
611
  createPostWithPostThread: {
214
612
  async handler(ctx) {
215
- const {
216
- threadMessageInput,
217
- channelId,
218
- responderId,
219
- accountId,
220
- postParentId,
221
- postId
222
- } = ctx.params;
223
- const {
224
- content,
225
- files,
226
- notificationParams
227
- } = threadMessageInput;
228
- const postPayload = {
229
- channel: channelId,
230
- message: content,
231
- editedBy: responderId || accountId,
232
- author: responderId || accountId,
233
- files,
234
- parentId: postParentId,
235
- props: notificationParams ? {
613
+ try {
614
+ logger.debug('Creating post with post thread', {
615
+ channelId: ctx.params.channelId,
616
+ accountId: ctx.params.accountId,
617
+ postParentId: ctx.params.postParentId
618
+ });
619
+ const {
620
+ threadMessageInput,
621
+ channelId,
622
+ responderId,
623
+ accountId,
624
+ postParentId,
625
+ postId
626
+ } = ctx.params;
627
+ const {
628
+ content,
629
+ files,
236
630
  notificationParams
237
- } : undefined
238
- };
239
- const post = await this.postService.createWithoutSubscription({
240
- ...(postId ? {
241
- _id: postId
242
- } : {}),
243
- ...postPayload
244
- });
245
- const postThread = await this.handlePostThreadCreate({
246
- ...ctx.params,
247
- post
248
- });
249
- return {
250
- post,
251
- postThread
252
- };
631
+ } = threadMessageInput;
632
+ const postPayload = {
633
+ channel: channelId,
634
+ message: content,
635
+ editedBy: responderId || accountId,
636
+ author: responderId || accountId,
637
+ files,
638
+ parentId: postParentId,
639
+ props: notificationParams ? {
640
+ notificationParams
641
+ } : undefined
642
+ };
643
+ const post = await this.postService.createWithoutSubscription({
644
+ ...(postId ? {
645
+ _id: postId
646
+ } : {}),
647
+ ...postPayload
648
+ });
649
+ if (post instanceof Error) {
650
+ logger.error('Failed to create post for post thread', {
651
+ error: post.message
652
+ });
653
+ throw post;
654
+ }
655
+ const postThread = await this.handlePostThreadCreate({
656
+ ...ctx.params,
657
+ post: post
658
+ });
659
+ logger.debug('Post with post thread created successfully', {
660
+ postId: post?.id,
661
+ threadId: postThread?.id
662
+ });
663
+ return {
664
+ post,
665
+ postThread
666
+ };
667
+ } catch (error) {
668
+ logger.error('Error in createPostWithPostThread action: %o', error);
669
+ throw error;
670
+ }
671
+ }
672
+ },
673
+ /**
674
+ * Gets the last message in a channel
675
+ */
676
+ getLastMessage: {
677
+ params: {
678
+ channelId: 'string'
679
+ },
680
+ async handler(ctx) {
681
+ try {
682
+ logger.debug('Getting last message', {
683
+ channelId: ctx.params.channelId
684
+ });
685
+ const {
686
+ channelId
687
+ } = ctx.params;
688
+ const result = await this.postService.getLastMessage(channelId);
689
+ if (result instanceof Error) {
690
+ logger.error('Failed to get last message', {
691
+ channelId,
692
+ error: result.message
693
+ });
694
+ throw result;
695
+ }
696
+ logger.debug('Last message retrieved successfully', {
697
+ channelId,
698
+ postId: result?.id
699
+ });
700
+ return result;
701
+ } catch (error) {
702
+ logger.error('Error in getLastMessage action: %o', error);
703
+ throw error;
704
+ }
705
+ }
706
+ },
707
+ /**
708
+ * Updates a post using base service method
709
+ */
710
+ updatePost: {
711
+ params: {
712
+ postId: 'string',
713
+ updates: 'object'
714
+ },
715
+ async handler(ctx) {
716
+ try {
717
+ logger.debug('Updating post', {
718
+ postId: ctx.params.postId,
719
+ updateKeys: Object.keys(ctx.params.updates || {})
720
+ });
721
+ const {
722
+ postId,
723
+ updates
724
+ } = ctx.params;
725
+ const result = await this.postService.update(postId, updates);
726
+ logger.debug('Post updated successfully', {
727
+ postId,
728
+ updatedPostId: result?.id
729
+ });
730
+ return result;
731
+ } catch (error) {
732
+ logger.error('Error in updatePost action: %o', error);
733
+ throw error;
734
+ }
735
+ }
736
+ },
737
+ /**
738
+ * Deletes a post using base service method
739
+ */
740
+ deletePost: {
741
+ params: {
742
+ postId: 'string'
743
+ },
744
+ async handler(ctx) {
745
+ try {
746
+ logger.debug('Deleting post', {
747
+ postId: ctx.params.postId
748
+ });
749
+ const {
750
+ postId
751
+ } = ctx.params;
752
+ const result = await this.postService.delete({
753
+ id: postId
754
+ });
755
+ logger.debug('Post deleted successfully', {
756
+ postId,
757
+ success: result
758
+ });
759
+ return result;
760
+ } catch (error) {
761
+ logger.error('Error in deletePost action: %o', error);
762
+ throw error;
763
+ }
764
+ }
765
+ },
766
+ /**
767
+ * Gets posts by channel using base service methods
768
+ */
769
+ getPostsByChannel: {
770
+ params: {
771
+ channelId: 'string',
772
+ limit: {
773
+ type: 'number',
774
+ optional: true,
775
+ default: 50
776
+ },
777
+ offset: {
778
+ type: 'number',
779
+ optional: true,
780
+ default: 0
781
+ }
782
+ },
783
+ async handler(ctx) {
784
+ try {
785
+ logger.debug('Getting posts by channel', {
786
+ channelId: ctx.params.channelId,
787
+ limit: ctx.params.limit,
788
+ offset: ctx.params.offset
789
+ });
790
+ const {
791
+ channelId,
792
+ limit,
793
+ offset
794
+ } = ctx.params;
795
+ // Use base service getAll with criteria
796
+ const result = await this.postService.getAll({
797
+ criteria: {
798
+ channel: channelId
799
+ },
800
+ pagination: {
801
+ limit,
802
+ offset
803
+ }
804
+ });
805
+ logger.debug('Posts retrieved successfully', {
806
+ channelId,
807
+ postCount: result?.length
808
+ });
809
+ return result;
810
+ } catch (error) {
811
+ logger.error('Error in getPostsByChannel action: %o', error);
812
+ throw error;
813
+ }
814
+ }
815
+ },
816
+ /**
817
+ * Gets posts with pagination and total count
818
+ */
819
+ getAllWithCount: {
820
+ params: {
821
+ criteria: {
822
+ type: 'object',
823
+ optional: true
824
+ },
825
+ sort: {
826
+ type: 'object',
827
+ optional: true
828
+ },
829
+ skip: {
830
+ type: 'number',
831
+ optional: true
832
+ },
833
+ limit: {
834
+ type: 'number',
835
+ optional: true
836
+ },
837
+ selectedFields: {
838
+ type: 'string',
839
+ optional: true
840
+ }
841
+ },
842
+ async handler(ctx) {
843
+ try {
844
+ logger.debug('Getting posts with count', {
845
+ criteria: ctx.params.criteria,
846
+ sort: ctx.params.sort,
847
+ skip: ctx.params.skip,
848
+ limit: ctx.params.limit
849
+ });
850
+ const result = await this.postService.getAllWithCount(ctx.params);
851
+ logger.debug('Posts retrieved with count successfully', {
852
+ dataCount: result?.data?.length,
853
+ totalCount: result?.totalCount
854
+ });
855
+ return result;
856
+ } catch (error) {
857
+ logger.error('Error in getAllWithCount action: %o', error);
858
+ throw error;
859
+ }
860
+ }
861
+ },
862
+ /**
863
+ * Health check endpoint
864
+ */
865
+ healthCheck: {
866
+ async handler(ctx) {
867
+ try {
868
+ logger.debug('Performing post service health check');
869
+ return {
870
+ status: 'healthy',
871
+ timestamp: new Date().toISOString(),
872
+ service: 'PostMoleculerService',
873
+ version: '1.0.0'
874
+ };
875
+ } catch (error) {
876
+ logger.error('Health check failed: %o', error);
877
+ throw error;
878
+ }
253
879
  }
254
880
  }
255
881
  }
256
882
  });
883
+ logger.info('PostMoleculerService initialized successfully');
257
884
  }
885
+ /**
886
+ * Handles post thread creation logic
887
+ *
888
+ * @description Creates or updates post threads with proper participant management
889
+ *
890
+ * @param {Object} params - Post thread creation parameters
891
+ * @returns {Promise<IPostThread>} - Created or updated post thread
892
+ */
258
893
  async handlePostThreadCreate({
259
894
  post,
260
895
  responderId,
@@ -263,58 +898,88 @@ class PostMoleculerService extends Service {
263
898
  orgId,
264
899
  postThreadId
265
900
  }) {
266
- const {
267
- role
268
- } = threadMessageInput;
269
- const channelId = post.channel?.toString();
270
- const postParentId = post.parentId?.toString();
271
- const postThread = await this.getPostThread({
272
- accountId,
273
- postThreadId,
274
- postParentId,
275
- channelId,
276
- role,
277
- orgId
278
- });
279
- const channel = await this.broker.call(`${MoleculerTopics.ChannelService}.get`, {
280
- id: channelId
281
- });
282
- const members = channel?.members?.map(m => ({
283
- user: m?.user,
284
- orgName: orgId,
285
- roles: role
286
- }));
287
- const defaultResponder = [{
288
- user: accountId,
289
- roles: role,
290
- orgName: orgId
291
- }];
292
- const responder = responderId ? [{
293
- user: responderId,
294
- roles: role,
295
- orgName: orgId
296
- }, ...defaultResponder] : defaultResponder;
297
- const normalizedParticipants = [...members, ...(postThread?.participants || []), ...responder].map(i => ({
298
- ...i,
299
- user: i.user.toString()
300
- }));
301
- const participants = uniqBy(normalizedParticipants, 'user');
302
- if (!postParentId && !postThread || postParentId && !postThread) {
303
- return this.createPostThread({
304
- post,
901
+ try {
902
+ logger.debug('Handling post thread creation', {
903
+ postId: post?.id,
904
+ accountId,
905
+ orgId,
906
+ hasExistingThread: !!postThreadId
907
+ });
908
+ const {
909
+ role
910
+ } = threadMessageInput;
911
+ const channelId = post.channel?.toString();
912
+ const postParentId = post.parentId?.toString();
913
+ const postThread = await this.getPostThread({
914
+ accountId,
915
+ postThreadId,
916
+ postParentId,
305
917
  channelId,
306
- participants,
307
- postParentId: postParentId ? postParentId : post.id
918
+ role,
919
+ orgId
920
+ });
921
+ const channel = await this.broker.call(`${MoleculerTopics.ChannelService}.get`, {
922
+ id: channelId
923
+ });
924
+ const members = channel?.members?.map(m => ({
925
+ user: m?.user,
926
+ orgName: orgId,
927
+ roles: role
928
+ }));
929
+ const defaultResponder = [{
930
+ user: accountId,
931
+ roles: role,
932
+ orgName: orgId
933
+ }];
934
+ const responder = responderId ? [{
935
+ user: responderId,
936
+ roles: role,
937
+ orgName: orgId
938
+ }, ...defaultResponder] : defaultResponder;
939
+ const normalizedParticipants = [...(members || []), ...(postThread?.participants || []), ...responder].map(i => ({
940
+ ...i,
941
+ user: i.user.toString()
942
+ }));
943
+ const participants = uniqBy(normalizedParticipants, 'user');
944
+ if (!postParentId && !postThread || postParentId && !postThread) {
945
+ const result = await this.createPostThread({
946
+ post,
947
+ channelId,
948
+ participants,
949
+ postParentId: postParentId ? postParentId : post.id
950
+ });
951
+ logger.debug('New post thread created', {
952
+ postId: post?.id,
953
+ threadId: result?.id,
954
+ participantCount: participants.length
955
+ });
956
+ return result;
957
+ }
958
+ const result = await this.dispatchPostEventsWithParentId({
959
+ post,
960
+ postThread,
961
+ accountId,
962
+ orgId,
963
+ role
964
+ });
965
+ logger.debug('Existing post thread updated', {
966
+ postId: post?.id,
967
+ threadId: result?.id
308
968
  });
969
+ return result;
970
+ } catch (error) {
971
+ logger.error('Error handling post thread creation: %o', error);
972
+ throw error;
309
973
  }
310
- return this.dispatchPostEventsWithParentId({
311
- post,
312
- postThread,
313
- accountId,
314
- orgId,
315
- role
316
- });
317
974
  }
975
+ /**
976
+ * Retrieves a post thread by criteria
977
+ *
978
+ * @description Finds existing post threads based on various criteria
979
+ *
980
+ * @param {Object} params - Search criteria
981
+ * @returns {Promise<IPostThread>} - Found post thread
982
+ */
318
983
  async getPostThread({
319
984
  postThreadId,
320
985
  channelId,
@@ -323,31 +988,55 @@ class PostMoleculerService extends Service {
323
988
  role,
324
989
  orgId
325
990
  }) {
326
- const criteria = {
327
- ...(postThreadId ? {
328
- _id: postThreadId
329
- } : {
330
- channel: channelId,
331
- post: postParentId,
332
- participants: {
333
- $elemMatch: {
334
- user: accountId,
335
- ...(role ? {
336
- roles: role
337
- } : {}),
338
- ...(orgId ? {
339
- orgName: orgId
340
- } : {})
991
+ try {
992
+ logger.debug('Getting post thread', {
993
+ postThreadId: postThreadId?.id,
994
+ channelId,
995
+ postParentId,
996
+ accountId,
997
+ orgId
998
+ });
999
+ const criteria = {
1000
+ ...(postThreadId ? {
1001
+ _id: postThreadId
1002
+ } : {
1003
+ channel: channelId,
1004
+ post: postParentId,
1005
+ participants: {
1006
+ $elemMatch: {
1007
+ user: accountId,
1008
+ ...(role ? {
1009
+ roles: role
1010
+ } : {}),
1011
+ ...(orgId ? {
1012
+ orgName: orgId
1013
+ } : {})
1014
+ }
341
1015
  }
342
- }
343
- })
344
- };
345
- const postThreads = await this.broker.call(`${MoleculerTopics.PostThreadService}.getAll`, {
346
- criteria
347
- });
348
- const [postThread] = postThreads ?? [];
349
- return postThread;
1016
+ })
1017
+ };
1018
+ const postThreads = await this.broker.call(`${MoleculerTopics.PostThreadService}.getAll`, {
1019
+ criteria
1020
+ });
1021
+ const [postThread] = postThreads ?? [];
1022
+ logger.debug('Post thread retrieved', {
1023
+ found: !!postThread,
1024
+ threadId: postThread?.id
1025
+ });
1026
+ return postThread;
1027
+ } catch (error) {
1028
+ logger.error('Error getting post thread: %o', error);
1029
+ throw error;
1030
+ }
350
1031
  }
1032
+ /**
1033
+ * Dispatches post events with parent ID for thread updates
1034
+ *
1035
+ * @description Handles event dispatching for post thread updates
1036
+ *
1037
+ * @param {Object} params - Event parameters
1038
+ * @returns {Promise<IPostThread>} - Updated post thread
1039
+ */
351
1040
  async dispatchPostEventsWithParentId({
352
1041
  post,
353
1042
  postThread,
@@ -355,39 +1044,80 @@ class PostMoleculerService extends Service {
355
1044
  orgId,
356
1045
  role
357
1046
  }) {
358
- await this.broker.emit('onUpdatePostThread', {
359
- post,
360
- postThread,
361
- accountId,
362
- orgId,
363
- role
364
- });
365
- return {
366
- ...postThread,
367
- replyCount: postThread.replyCount + 1,
368
- lastReplyAt: post.createdAt
369
- };
1047
+ try {
1048
+ logger.debug('Dispatching post events with parent ID', {
1049
+ postId: post?.id,
1050
+ threadId: postThread?.id,
1051
+ accountId,
1052
+ orgId
1053
+ });
1054
+ await this.broker.emit('onUpdatePostThread', {
1055
+ post,
1056
+ postThread,
1057
+ accountId,
1058
+ orgId,
1059
+ role
1060
+ });
1061
+ const updatedThread = {
1062
+ ...postThread,
1063
+ replyCount: postThread.replyCount + 1,
1064
+ lastReplyAt: post.createdAt
1065
+ };
1066
+ logger.debug('Post events dispatched successfully', {
1067
+ postId: post?.id,
1068
+ threadId: updatedThread?.id,
1069
+ newReplyCount: updatedThread.replyCount
1070
+ });
1071
+ return updatedThread;
1072
+ } catch (error) {
1073
+ logger.error('Error dispatching post events: %o', error);
1074
+ throw error;
1075
+ }
370
1076
  }
1077
+ /**
1078
+ * Creates a new post thread
1079
+ *
1080
+ * @description Creates a new thread for organizing related posts
1081
+ *
1082
+ * @param {Object} params - Thread creation parameters
1083
+ * @returns {Promise<IPostThread>} - Created post thread
1084
+ */
371
1085
  async createPostThread({
372
1086
  channelId,
373
1087
  postParentId,
374
1088
  post,
375
1089
  participants
376
1090
  }) {
377
- const postThreadData = {
378
- post: postParentId,
379
- channel: channelId,
380
- replyCount: 0,
381
- lastReplyAt: post.createdAt,
382
- participants
383
- };
384
- const postThread = await this.broker.call(`${MoleculerTopics.PostThreadService}.create`, {
385
- data: postThreadData
386
- });
387
- await this.broker.emit('onCreatePostThread', {
388
- post,
389
- postThread
390
- });
391
- return postThread;
1091
+ try {
1092
+ logger.debug('Creating new post thread', {
1093
+ channelId,
1094
+ postParentId,
1095
+ postId: post?.id,
1096
+ participantCount: participants?.length
1097
+ });
1098
+ const postThreadData = {
1099
+ post: postParentId,
1100
+ channel: channelId,
1101
+ replyCount: 0,
1102
+ lastReplyAt: post.createdAt,
1103
+ participants
1104
+ };
1105
+ const postThread = await this.broker.call(`${MoleculerTopics.PostThreadService}.create`, {
1106
+ data: postThreadData
1107
+ });
1108
+ await this.broker.emit('onCreatePostThread', {
1109
+ post,
1110
+ postThread
1111
+ });
1112
+ logger.debug('Post thread created successfully', {
1113
+ threadId: postThread?.id,
1114
+ channelId,
1115
+ postParentId
1116
+ });
1117
+ return postThread;
1118
+ } catch (error) {
1119
+ logger.error('Error creating post thread: %o', error);
1120
+ throw error;
1121
+ }
392
1122
  }
393
1123
  }export{PostMoleculerService};//# sourceMappingURL=post-moleculer-service.js.map