@messenger-box/platform-server 10.0.3-alpha.50 → 10.0.3-alpha.54

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 (111) hide show
  1. package/lib/containers/containers.js.map +1 -1
  2. package/lib/graphql/resolvers/channel-member.d.ts +2 -1
  3. package/lib/graphql/resolvers/channel-member.js +13 -3
  4. package/lib/graphql/resolvers/channel-member.js.map +1 -1
  5. package/lib/graphql/resolvers/channel.d.ts +2 -1
  6. package/lib/graphql/resolvers/channel.js +260 -126
  7. package/lib/graphql/resolvers/channel.js.map +1 -1
  8. package/lib/graphql/resolvers/extended-token-account.d.ts +2 -1
  9. package/lib/graphql/resolvers/extended-token-account.js +90 -23
  10. package/lib/graphql/resolvers/extended-token-account.js.map +1 -1
  11. package/lib/graphql/resolvers/post-thread.js +285 -179
  12. package/lib/graphql/resolvers/post-thread.js.map +1 -1
  13. package/lib/graphql/resolvers/post.js +669 -242
  14. package/lib/graphql/resolvers/post.js.map +1 -1
  15. package/lib/graphql/resolvers/reaction.d.ts +2 -1
  16. package/lib/graphql/resolvers/reaction.js +96 -14
  17. package/lib/graphql/resolvers/reaction.js.map +1 -1
  18. package/lib/graphql/schema/channel.graphql +331 -39
  19. package/lib/graphql/schema/channel.graphql.js +1 -1
  20. package/lib/graphql/schema/post-thread.graphql +157 -21
  21. package/lib/graphql/schema/post-thread.graphql.js +1 -1
  22. package/lib/graphql/schema/post.graphql +265 -40
  23. package/lib/graphql/schema/post.graphql.js +1 -1
  24. package/lib/graphql/schema/reaction.graphql +71 -13
  25. package/lib/graphql/schema/reaction.graphql.js +1 -1
  26. package/lib/graphql/schema/users.graphql +76 -13
  27. package/lib/graphql/schema/users.graphql.js +1 -1
  28. package/lib/plugins/channel-moleculer-service.d.ts +21 -1
  29. package/lib/plugins/channel-moleculer-service.js +417 -115
  30. package/lib/plugins/channel-moleculer-service.js.map +1 -1
  31. package/lib/plugins/extended-token-account-moleculer-service.d.ts +25 -1
  32. package/lib/plugins/extended-token-account-moleculer-service.js +348 -22
  33. package/lib/plugins/extended-token-account-moleculer-service.js.map +1 -1
  34. package/lib/plugins/messenger-notification-moleculer-service.d.ts +26 -3
  35. package/lib/plugins/messenger-notification-moleculer-service.js +403 -57
  36. package/lib/plugins/messenger-notification-moleculer-service.js.map +1 -1
  37. package/lib/plugins/post-moleculer-service.d.ts +84 -20
  38. package/lib/plugins/post-moleculer-service.js +891 -259
  39. package/lib/plugins/post-moleculer-service.js.map +1 -1
  40. package/lib/plugins/post-thread-moleculer-service.d.ts +33 -1
  41. package/lib/plugins/post-thread-moleculer-service.js +320 -13
  42. package/lib/plugins/post-thread-moleculer-service.js.map +1 -1
  43. package/lib/services/channel-service.d.ts +185 -33
  44. package/lib/services/channel-service.js +767 -282
  45. package/lib/services/channel-service.js.map +1 -1
  46. package/lib/services/extended-token-account-service.d.ts +127 -14
  47. package/lib/services/extended-token-account-service.js +459 -52
  48. package/lib/services/extended-token-account-service.js.map +1 -1
  49. package/lib/services/messenger-notification-service.d.ts +106 -13
  50. package/lib/services/messenger-notification-service.js +824 -442
  51. package/lib/services/messenger-notification-service.js.map +1 -1
  52. package/lib/services/post-service.d.ts +176 -16
  53. package/lib/services/post-service.js +553 -119
  54. package/lib/services/post-service.js.map +1 -1
  55. package/lib/services/post-thread-service.d.ts +114 -6
  56. package/lib/services/post-thread-service.js +397 -18
  57. package/lib/services/post-thread-service.js.map +1 -1
  58. package/lib/services/proxy-services/channel-microservice.d.ts +4 -3
  59. package/lib/services/proxy-services/channel-microservice.js +12 -9
  60. package/lib/services/proxy-services/channel-microservice.js.map +1 -1
  61. package/lib/services/proxy-services/messenger-notification-microservice.d.ts +128 -8
  62. package/lib/services/proxy-services/messenger-notification-microservice.js +324 -29
  63. package/lib/services/proxy-services/messenger-notification-microservice.js.map +1 -1
  64. package/lib/services/proxy-services/post-microservice.d.ts +186 -13
  65. package/lib/services/proxy-services/post-microservice.js +543 -59
  66. package/lib/services/proxy-services/post-microservice.js.map +1 -1
  67. package/lib/services/proxy-services/post-thread-microservice.d.ts +134 -4
  68. package/lib/services/proxy-services/post-thread-microservice.js +387 -10
  69. package/lib/services/proxy-services/post-thread-microservice.js.map +1 -1
  70. package/lib/services/proxy-services/reaction-microservice.d.ts +161 -3
  71. package/lib/services/proxy-services/reaction-microservice.js +474 -2
  72. package/lib/services/proxy-services/reaction-microservice.js.map +1 -1
  73. package/lib/services/reaction-service.d.ts +124 -4
  74. package/lib/services/reaction-service.js +415 -3
  75. package/lib/services/reaction-service.js.map +1 -1
  76. package/lib/store/models/channel.d.ts +2 -3
  77. package/lib/store/models/channel.js +169 -71
  78. package/lib/store/models/channel.js.map +1 -1
  79. package/lib/store/models/post-thread.d.ts +3 -3
  80. package/lib/store/models/post-thread.js +96 -14
  81. package/lib/store/models/post-thread.js.map +1 -1
  82. package/lib/store/models/post.d.ts +2 -3
  83. package/lib/store/models/post.js +85 -18
  84. package/lib/store/models/post.js.map +1 -1
  85. package/lib/store/models/reaction.d.ts +2 -3
  86. package/lib/store/models/reaction.js +67 -8
  87. package/lib/store/models/reaction.js.map +1 -1
  88. package/lib/store/repositories/channel-repository.d.ts +6 -6
  89. package/lib/store/repositories/channel-repository.js +5 -2
  90. package/lib/store/repositories/channel-repository.js.map +1 -1
  91. package/lib/store/repositories/post-repository.d.ts +6 -6
  92. package/lib/store/repositories/post-repository.js +5 -2
  93. package/lib/store/repositories/post-repository.js.map +1 -1
  94. package/lib/store/repositories/post-thread-repository.d.ts +6 -6
  95. package/lib/store/repositories/post-thread-repository.js +5 -2
  96. package/lib/store/repositories/post-thread-repository.js.map +1 -1
  97. package/lib/store/repositories/reaction-repository.d.ts +6 -6
  98. package/lib/store/repositories/reaction-repository.js +5 -2
  99. package/lib/store/repositories/reaction-repository.js.map +1 -1
  100. package/lib/templates/repositories/ChannelRepository.ts.template +3 -3
  101. package/lib/templates/repositories/PostRepository.ts.template +3 -3
  102. package/lib/templates/repositories/PostThreadRepository.ts.template +3 -3
  103. package/lib/templates/repositories/ReactionRepository.ts.template +3 -4
  104. package/lib/templates/services/ChannelService.ts.template +277 -38
  105. package/lib/templates/services/ExtendedTokenAccountService.ts.template +93 -8
  106. package/lib/templates/services/PostService.ts.template +182 -20
  107. package/lib/templates/services/PostThreadService.ts.template +100 -5
  108. package/lib/templates/services/ReactionService.ts.template +129 -2
  109. package/package.json +3 -3
  110. package/lib/store/models/common-options.js +0 -20
  111. package/lib/store/models/common-options.js.map +0 -1
@@ -1,10 +1,30 @@
1
- import {__decorate,__param,__metadata}from'tslib';import'@cdm-logger/core';import {inject}from'inversify';import {set}from'lodash-es';import {SERVER_TYPES,FileRefType}from'common/server';import {BaseService}from'@common-stack/store-mongo';import {PubSubEngine}from'graphql-subscriptions';import {CommonType}from'@common-stack/core';import {ServiceBroker}from'moleculer';import {ChannelRepository}from'../store/repositories/channel-repository.js';import {PostRepository}from'../store/repositories/post-repository.js';import'../store/repositories/post-thread-repository.js';import'../store/repositories/reaction-repository.js';import {PostTypes}from'../preferences/settings/post-settings.js';import'../preferences/permissions/inbox-permission-contribution.js';import'../preferences/permissions/inbox-roles-permission-overwrite.js';import {config}from'../config/env-config.js';var PostService_1;
2
- let PostService = PostService_1 = class PostService extends BaseService {
1
+ import {__decorate,__param,__metadata}from'tslib';import'@cdm-logger/core';import {inject}from'inversify';import {set}from'lodash-es';import {SERVER_TYPES,FileRefType}from'common/server';import {BaseService2}from'@common-stack/store-mongo';import {PubSubEngine}from'graphql-subscriptions';import {CommonType}from'@common-stack/core';import {ServiceBroker}from'moleculer';import {DisposableCollection}from'@adminide-stack/core';import {ChannelRepository}from'../store/repositories/channel-repository.js';import {PostRepository}from'../store/repositories/post-repository.js';import'../store/repositories/post-thread-repository.js';import'../store/repositories/reaction-repository.js';import {PostTypes}from'../preferences/settings/post-settings.js';import'../preferences/permissions/inbox-permission-contribution.js';import'../preferences/permissions/inbox-roles-permission-overwrite.js';import {config}from'../config/env-config.js';var PostService_1;
2
+ /**
3
+ * Post Service Implementation
4
+ *
5
+ * This service handles comprehensive post management within the messenger platform,
6
+ * providing operations for creating, updating, managing posts and their associated
7
+ * content including file attachments, notifications, threading, and real-time
8
+ * message delivery across channels and organizations.
9
+ *
10
+ * Key capabilities:
11
+ * - Post lifecycle management (creation, updates, deletion)
12
+ * - File attachment handling and upload management
13
+ * - Real-time message delivery and notifications
14
+ * - Post threading and conversation management
15
+ * - Message status tracking (read, delivered)
16
+ * - Channel integration and message counting
17
+ * - Expo push notification integration
18
+ * - File upload link generation and management
19
+ */
20
+ // @ts-ignore - Type compatibility issue between BaseService2 and IPostService
21
+ let PostService = PostService_1 = class PostService extends BaseService2 {
3
22
  channelRepo;
4
23
  fileInfoService;
5
24
  messengerNotificationService;
6
25
  broker;
7
26
  pubsub;
27
+ toDispose = new DisposableCollection();
8
28
  logger;
9
29
  constructor(repository, channelRepo, fileInfoService, messengerNotificationService, broker, pubsub, logger) {
10
30
  super(repository);
@@ -17,39 +37,59 @@ let PostService = PostService_1 = class PostService extends BaseService {
17
37
  className: PostService_1.name
18
38
  });
19
39
  }
20
- createFileUploadLink(postId, filename, userId) {
21
- return this.fileInfoService.uploadByUrl({
22
- filename,
23
- refType: FileRefType.Post,
24
- ref: postId,
25
- userId
26
- });
40
+ /**
41
+ * Disposes of resources used by the service
42
+ */
43
+ dispose() {
44
+ this.toDispose.dispose();
45
+ }
46
+ /**
47
+ * Creates a file upload link for a post
48
+ *
49
+ * @description Generates a secure upload URL for attaching files to posts
50
+ *
51
+ * @param {string} postId - The post identifier
52
+ * @param {string} filename - The name of the file to upload
53
+ * @param {string} userId - The user performing the upload
54
+ * @returns {Promise<string | Error>} - Upload URL or error
55
+ */
56
+ async createFileUploadLink(postId, filename, userId) {
57
+ try {
58
+ if (!postId || !filename || !userId) {
59
+ return new Error('Post ID, filename, and user ID are required');
60
+ }
61
+ const uploadUrl = await this.fileInfoService.uploadByUrl({
62
+ filename,
63
+ refType: FileRefType.Post,
64
+ ref: postId,
65
+ userId
66
+ });
67
+ this.logger.debug('File upload link created', {
68
+ postId,
69
+ filename,
70
+ userId
71
+ });
72
+ return uploadUrl;
73
+ } catch (error) {
74
+ this.logger.error('Error creating file upload link: %o', error);
75
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating upload link');
76
+ }
27
77
  }
78
+ /**
79
+ * Attaches an uploaded file to a post
80
+ *
81
+ * @description Processes and attaches a completed file upload to a post
82
+ *
83
+ * @param {string} postId - The post identifier
84
+ * @param {IUploadedFileInput} file - The uploaded file information
85
+ * @param {string} createdBy - The user who uploaded the file
86
+ * @returns {Promise<IFileInfo | Error>} - File information or error
87
+ */
28
88
  async attachUploadedFile(postId, file, createdBy) {
29
- const {
30
- id
31
- } = await this.fileInfoService.createUploadedFile({
32
- ...file,
33
- refType: FileRefType.Post,
34
- ref: postId,
35
- createdBy
36
- });
37
- const fileResponse = await this.fileInfoService.get(id);
38
- return {
39
- ...fileResponse,
40
- url: this.fileInfoService.getDefaultImage(fileResponse.url)
41
- };
42
- }
43
- createFilesUploadLink(postId, filenames, userId) {
44
- return Promise.all(filenames.map(filename => this.fileInfoService.uploadByUrl({
45
- filename,
46
- refType: FileRefType.Post,
47
- ref: postId,
48
- userId
49
- })));
50
- }
51
- attachUploadedFiles(postId, files, createdBy) {
52
- return Promise.all(files.map(async file => {
89
+ try {
90
+ if (!postId || !file || !createdBy) {
91
+ return new Error('Post ID, file data, and creator ID are required');
92
+ }
53
93
  const {
54
94
  id
55
95
  } = await this.fileInfoService.createUploadedFile({
@@ -59,111 +99,505 @@ let PostService = PostService_1 = class PostService extends BaseService {
59
99
  createdBy
60
100
  });
61
101
  const fileResponse = await this.fileInfoService.get(id);
62
- return {
102
+ const result = {
63
103
  ...fileResponse,
64
104
  url: this.fileInfoService.getDefaultImage(fileResponse.url)
65
105
  };
66
- }));
106
+ this.logger.debug('File attached to post', {
107
+ postId,
108
+ fileId: id,
109
+ createdBy
110
+ });
111
+ return result;
112
+ } catch (error) {
113
+ this.logger.error('Error attaching uploaded file: %o', error);
114
+ return error instanceof Error ? error : new Error('Unknown error occurred while attaching file');
115
+ }
116
+ }
117
+ /**
118
+ * Creates upload links for multiple files
119
+ *
120
+ * @description Generates secure upload URLs for multiple files to be attached to a post
121
+ *
122
+ * @param {string} postId - The post identifier
123
+ * @param {string[]} filenames - Array of file names
124
+ * @param {string} userId - The user performing the uploads
125
+ * @returns {Promise<string[] | Error>} - Array of upload URLs or error
126
+ */
127
+ async createFilesUploadLink(postId, filenames, userId) {
128
+ try {
129
+ if (!postId || !filenames || !Array.isArray(filenames) || !userId) {
130
+ return new Error('Post ID, filenames array, and user ID are required');
131
+ }
132
+ if (filenames.length === 0) {
133
+ return new Error('At least one filename is required');
134
+ }
135
+ const uploadUrls = await Promise.all(filenames.map(filename => this.fileInfoService.uploadByUrl({
136
+ filename,
137
+ refType: FileRefType.Post,
138
+ ref: postId,
139
+ userId
140
+ })));
141
+ this.logger.debug('Multiple file upload links created', {
142
+ postId,
143
+ fileCount: filenames.length,
144
+ userId
145
+ });
146
+ return uploadUrls;
147
+ } catch (error) {
148
+ this.logger.error('Error creating multiple file upload links: %o', error);
149
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating upload links');
150
+ }
151
+ }
152
+ /**
153
+ * Attaches multiple uploaded files to a post
154
+ *
155
+ * @description Processes and attaches multiple completed file uploads to a post
156
+ *
157
+ * @param {string} postId - The post identifier
158
+ * @param {IUploadedFileInput[]} files - Array of uploaded file information
159
+ * @param {string} createdBy - The user who uploaded the files
160
+ * @returns {Promise<IFileInfo[] | Error>} - Array of file information or error
161
+ */
162
+ async attachUploadedFiles(postId, files, createdBy) {
163
+ try {
164
+ if (!postId || !files || !Array.isArray(files) || !createdBy) {
165
+ return new Error('Post ID, files array, and creator ID are required');
166
+ }
167
+ if (files.length === 0) {
168
+ return new Error('At least one file is required');
169
+ }
170
+ const fileResults = await Promise.all(files.map(async file => {
171
+ const {
172
+ id
173
+ } = await this.fileInfoService.createUploadedFile({
174
+ ...file,
175
+ refType: FileRefType.Post,
176
+ ref: postId,
177
+ createdBy
178
+ });
179
+ const fileResponse = await this.fileInfoService.get(id);
180
+ return {
181
+ ...fileResponse,
182
+ url: this.fileInfoService.getDefaultImage(fileResponse.url)
183
+ };
184
+ }));
185
+ this.logger.debug('Multiple files attached to post', {
186
+ postId,
187
+ fileCount: files.length,
188
+ createdBy
189
+ });
190
+ return fileResults;
191
+ } catch (error) {
192
+ this.logger.error('Error attaching multiple uploaded files: %o', error);
193
+ return error instanceof Error ? error : new Error('Unknown error occurred while attaching files');
194
+ }
67
195
  }
196
+ /**
197
+ * Creates a new post with full integration
198
+ *
199
+ * @description Creates a post with channel updates, notifications, and real-time publishing
200
+ *
201
+ * @param {IPostServiceInput} data - Post creation data
202
+ * @returns {Promise<AsDomainType<IPostModel> | Error>} - Created post or error
203
+ */
204
+ // @ts-ignore - Type compatibility issue between interface and implementation
68
205
  async create(data) {
69
- const post = await super.create(data);
70
- const {
71
- channel
72
- } = data;
73
- // Accessing private property
74
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
75
- // @ts-ignore
76
- await this.channelRepo.model.updateOne({
77
- _id: channel
78
- }, {
79
- lastPostAt: post.createdAt,
80
- $inc: {
81
- totalMsgCount: 1,
82
- totalMsgCountRoot: 1,
83
- 'members.$[elem].msgCountRoot': 1,
84
- 'members.$[elem].msgCount': 1
85
- }
86
- }, {
87
- arrayFilters: [{
88
- 'elem.user': data.author
89
- }]
90
- });
91
- await this.pubsub.publish(`POST_CREATED.${channel}`, post);
92
- await this.sendExpoNotification(post);
93
- // if (post?.props?.notificationParams) await this.messengerNotificationService.sendExpoNotificationOnPost(post);
94
- this.logger.trace('Post created');
95
- return post;
206
+ try {
207
+ if (!data) {
208
+ return new Error('Post data is required');
209
+ }
210
+ if (!data.channel) {
211
+ return new Error('Channel is required for post creation');
212
+ }
213
+ if (!data.author) {
214
+ return new Error('Author is required for post creation');
215
+ }
216
+ // Create the post
217
+ const postData = {
218
+ ...data,
219
+ createdAt: new Date(),
220
+ updatedAt: new Date()
221
+ }; // Type assertion for compatibility
222
+ const post = await this.repository.create(postData);
223
+ if (!post) {
224
+ return new Error('Failed to create post');
225
+ }
226
+ const {
227
+ channel
228
+ } = data;
229
+ // Update channel statistics
230
+ // @ts-ignore - Accessing private property for channel updates
231
+ await this.channelRepo.model.updateOne({
232
+ _id: channel
233
+ }, {
234
+ lastPostAt: post.createdAt,
235
+ $inc: {
236
+ totalMsgCount: 1,
237
+ totalMsgCountRoot: 1,
238
+ 'members.$[elem].msgCountRoot': 1,
239
+ 'members.$[elem].msgCount': 1
240
+ }
241
+ }, {
242
+ arrayFilters: [{
243
+ 'elem.user': data.author
244
+ }]
245
+ });
246
+ // Publish real-time update
247
+ await this.pubsub.publish(`POST_CREATED.${channel}`, post);
248
+ // Send push notification
249
+ await this.sendExpoNotification(post);
250
+ this.logger.debug('Post created successfully', {
251
+ postId: post.id,
252
+ channelId: channel,
253
+ authorId: data.author
254
+ });
255
+ return post;
256
+ } catch (error) {
257
+ this.logger.error('Error creating post: %o', error);
258
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating post');
259
+ }
96
260
  }
261
+ /**
262
+ * Creates a post without real-time subscription
263
+ *
264
+ * @description Creates a post with channel updates but without real-time publishing
265
+ *
266
+ * @param {IPostServiceInput} data - Post creation data
267
+ * @returns {Promise<AsDomainType<IPostModel> | Error>} - Created post or error
268
+ */
269
+ // @ts-ignore - Type compatibility issue between interface and implementation
97
270
  async createWithoutSubscription(data) {
98
- const post = await super.create(data);
99
- const {
100
- channel
101
- } = data;
102
- await this.channelRepo.model.updateOne({
103
- _id: channel
104
- }, {
105
- lastPostAt: post.createdAt,
106
- $inc: {
107
- totalMsgCount: 1,
108
- totalMsgCountRoot: 1,
109
- 'members.$[elem].msgCountRoot': 1,
110
- 'members.$[elem].msgCount': 1
111
- }
112
- }, {
113
- arrayFilters: [{
114
- 'elem.user': data.author
115
- }]
116
- });
117
- return post;
271
+ try {
272
+ if (!data) {
273
+ return new Error('Post data is required');
274
+ }
275
+ if (!data.channel) {
276
+ return new Error('Channel is required for post creation');
277
+ }
278
+ if (!data.author) {
279
+ return new Error('Author is required for post creation');
280
+ }
281
+ // Create the post
282
+ const postData = {
283
+ ...data,
284
+ createdAt: new Date(),
285
+ updatedAt: new Date()
286
+ }; // Type assertion for compatibility
287
+ const post = await this.repository.create(postData);
288
+ if (!post) {
289
+ return new Error('Failed to create post');
290
+ }
291
+ const {
292
+ channel
293
+ } = data;
294
+ // Update channel statistics without real-time publishing
295
+ // @ts-ignore - Accessing private property for channel updates
296
+ await this.channelRepo.model.updateOne({
297
+ _id: channel
298
+ }, {
299
+ lastPostAt: post.createdAt,
300
+ $inc: {
301
+ totalMsgCount: 1,
302
+ totalMsgCountRoot: 1,
303
+ 'members.$[elem].msgCountRoot': 1,
304
+ 'members.$[elem].msgCount': 1
305
+ }
306
+ }, {
307
+ arrayFilters: [{
308
+ 'elem.user': data.author
309
+ }]
310
+ });
311
+ this.logger.debug('Post created without subscription', {
312
+ postId: post.id,
313
+ channelId: channel,
314
+ authorId: data.author
315
+ });
316
+ return post;
317
+ } catch (error) {
318
+ this.logger.error('Error creating post without subscription: %o', error);
319
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating post');
320
+ }
118
321
  }
119
- deleteFile(url) {
120
- return this.fileInfoService.deleteByUrl(url);
322
+ /**
323
+ * Deletes a file by URL
324
+ *
325
+ * @description Removes a file from storage using its URL
326
+ *
327
+ * @param {string} url - The file URL to delete
328
+ * @returns {Promise<boolean | Error>} - Success status or error
329
+ */
330
+ async deleteFile(url) {
331
+ try {
332
+ if (!url) {
333
+ return new Error('File URL is required');
334
+ }
335
+ const success = await this.fileInfoService.deleteByUrl(url);
336
+ this.logger.debug('File deleted', {
337
+ url,
338
+ success
339
+ });
340
+ return success;
341
+ } catch (error) {
342
+ this.logger.error('Error deleting file: %o', error);
343
+ return error instanceof Error ? error : new Error('Unknown error occurred while deleting file');
344
+ }
121
345
  }
346
+ /**
347
+ * Marks a message as read by a user
348
+ *
349
+ * @description Updates message status to indicate it has been read by a specific user
350
+ *
351
+ * @param {IMessageIdentifier} messageId - Message identifier
352
+ * @param {string} user - User ID who read the message
353
+ * @returns {Promise<boolean | Error>} - Success status or error
354
+ */
122
355
  async readMessage(messageId, user) {
123
- await this.update(messageId.messageId, {
124
- props: {
125
- [`[${user}]`]: set({}, PostTypes.isRead, true)
356
+ try {
357
+ if (!messageId?.messageId || !user) {
358
+ return new Error('Message ID and user ID are required');
126
359
  }
127
- });
128
- return true;
360
+ await this.update(messageId.messageId, {
361
+ props: {
362
+ [`[${user}]`]: set({}, PostTypes.isRead, true)
363
+ }
364
+ });
365
+ this.logger.debug('Message marked as read', {
366
+ messageId: messageId.messageId,
367
+ userId: user
368
+ });
369
+ return true;
370
+ } catch (error) {
371
+ this.logger.error('Error marking message as read: %o', error);
372
+ return error instanceof Error ? error : new Error('Unknown error occurred while marking message as read');
373
+ }
129
374
  }
375
+ /**
376
+ * Marks a message as delivered to a user
377
+ *
378
+ * @description Updates message status to indicate it has been delivered to a specific user
379
+ *
380
+ * @param {IMessageIdentifier} messageId - Message identifier
381
+ * @param {string} user - User ID who received the message
382
+ * @returns {Promise<boolean | Error>} - Success status or error
383
+ */
130
384
  async deliverMessage(messageId, user) {
131
- await this.update(messageId.messageId, {
132
- props: {
133
- [`[${user}]`]: set({}, PostTypes.isDelivered, true)
385
+ try {
386
+ if (!messageId?.messageId || !user) {
387
+ return new Error('Message ID and user ID are required');
134
388
  }
135
- });
136
- return true;
137
- }
138
- async sendExpoNotification(post) {
139
- if (post?.props?.notificationParams && (!post?.type || post?.type !== 'ALERT')) {
140
- await this.messengerNotificationService.sendExpoNotificationOnPost(post);
141
- } else if (!post?.type || post?.type !== 'ALERT') {
142
- const notificationData = {
143
- url: config.INBOX_MESSEGE_PATH,
144
- params: {
145
- channelId: post?.channel,
146
- hideTabBar: true
147
- },
148
- screen: 'DialogMessages',
149
- other: {
150
- sound: 'default'
389
+ await this.update(messageId.messageId, {
390
+ props: {
391
+ [`[${user}]`]: set({}, PostTypes.isDelivered, true)
151
392
  }
152
- };
153
- await this.messengerNotificationService.sendExpoNotificationOnPost(post, notificationData);
393
+ });
394
+ this.logger.debug('Message marked as delivered', {
395
+ messageId: messageId.messageId,
396
+ userId: user
397
+ });
398
+ return true;
399
+ } catch (error) {
400
+ this.logger.error('Error marking message as delivered: %o', error);
401
+ return error instanceof Error ? error : new Error('Unknown error occurred while marking message as delivered');
154
402
  }
155
403
  }
156
- // eslint-disable-next-line class-methods-use-this
157
- createPostWithPostThread(data) {
158
- throw new Error('Not implemented');
404
+ /**
405
+ * Creates a post with associated post thread
406
+ *
407
+ * @description Creates both a post and its associated thread for threaded conversations
408
+ *
409
+ * @param {CreatePostThreadOptions} data - Post and thread creation options
410
+ * @returns {Promise<{post: AsDomainType<IPostModel>; postThread: IPostThread} | Error>} - Created post and thread or error
411
+ */
412
+ // @ts-ignore - Type compatibility issue between interface and implementation
413
+ async createPostWithPostThread(data) {
414
+ try {
415
+ if (!data) {
416
+ return new Error('Post thread creation data is required');
417
+ }
418
+ // This would require integration with PostThreadService
419
+ // For now, return an error indicating it needs implementation
420
+ return new Error('Post thread creation is not yet implemented');
421
+ } catch (error) {
422
+ this.logger.error('Error creating post with thread: %o', error);
423
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating post with thread');
424
+ }
159
425
  }
426
+ /**
427
+ * Retrieves the last message in a channel
428
+ *
429
+ * @description Gets the most recent post/message from a specific channel
430
+ *
431
+ * @param {string} channelId - The channel identifier
432
+ * @returns {Promise<AsDomainType<IPostModel> | Error>} - Last message or error
433
+ */
434
+ // @ts-ignore - Type compatibility issue between interface and implementation
160
435
  async getLastMessage(channelId) {
161
- const post = await this.repository.model.findOne({
162
- channel: channelId
163
- }).sort({
164
- createdAt: -1
165
- });
166
- return post;
436
+ try {
437
+ if (!channelId) {
438
+ return new Error('Channel ID is required');
439
+ }
440
+ // @ts-ignore - Accessing private property for direct query
441
+ const post = await this.repository.model.findOne({
442
+ channel: channelId
443
+ }).sort({
444
+ createdAt: -1
445
+ });
446
+ if (!post) {
447
+ return new Error('No messages found in channel');
448
+ }
449
+ this.logger.debug('Last message retrieved', {
450
+ channelId,
451
+ postId: post._id
452
+ });
453
+ return post;
454
+ } catch (error) {
455
+ this.logger.error('Error getting last message: %o', error);
456
+ return error instanceof Error ? error : new Error('Unknown error occurred while getting last message');
457
+ }
458
+ }
459
+ /**
460
+ * Gets posts by channel with pagination
461
+ *
462
+ * @description Retrieves posts from a channel with pagination support
463
+ *
464
+ * @param {string} channelId - The channel identifier
465
+ * @param {number} limit - Maximum number of posts to return
466
+ * @param {number} offset - Number of posts to skip
467
+ * @returns {Promise<Array<AsDomainType<IPostModel>> | Error>} - Array of posts or error
468
+ */
469
+ async getPostsByChannel(channelId, limit = 50, offset = 0) {
470
+ try {
471
+ if (!channelId) {
472
+ return new Error('Channel ID is required');
473
+ }
474
+ const posts = await this.getAll({
475
+ criteria: {
476
+ channel: channelId
477
+ }
478
+ });
479
+ // Apply manual pagination
480
+ const paginatedPosts = posts.slice(offset, offset + limit);
481
+ this.logger.debug('Posts retrieved by channel', {
482
+ channelId,
483
+ count: paginatedPosts.length,
484
+ limit,
485
+ offset
486
+ });
487
+ return paginatedPosts;
488
+ } catch (error) {
489
+ this.logger.error('Error getting posts by channel: %o', error);
490
+ return error instanceof Error ? error : new Error('Unknown error occurred while getting posts by channel');
491
+ }
492
+ }
493
+ /**
494
+ * Updates a post
495
+ *
496
+ * @description Updates post content and metadata
497
+ *
498
+ * @param {string} postId - The post identifier
499
+ * @param {Partial<IPostServiceInput>} updates - Update data
500
+ * @returns {Promise<AsDomainType<IPostModel> | Error>} - Updated post or error
501
+ */
502
+ async updatePost(postId, updates) {
503
+ try {
504
+ if (!postId) {
505
+ return new Error('Post ID is required');
506
+ }
507
+ if (!updates || Object.keys(updates).length === 0) {
508
+ return new Error('Updates are required');
509
+ }
510
+ // Get existing post
511
+ const existingPost = await this.get(postId);
512
+ if (!existingPost) {
513
+ return new Error('Post not found');
514
+ }
515
+ // Prepare update data
516
+ const updateData = {
517
+ ...updates,
518
+ updatedAt: new Date()
519
+ }; // Type assertion for compatibility
520
+ // Update the post
521
+ const updatedPost = await this.update(postId, updateData);
522
+ if (!updatedPost) {
523
+ return new Error('Failed to update post');
524
+ }
525
+ this.logger.debug('Post updated successfully', {
526
+ postId,
527
+ updates: Object.keys(updates)
528
+ });
529
+ return updatedPost;
530
+ } catch (error) {
531
+ this.logger.error('Error updating post: %o', error);
532
+ return error instanceof Error ? error : new Error('Unknown error occurred while updating post');
533
+ }
534
+ }
535
+ /**
536
+ * Deletes a post
537
+ *
538
+ * @description Soft deletes a post and its associated data
539
+ *
540
+ * @param {string} postId - The post identifier
541
+ * @returns {Promise<boolean | Error>} - Success status or error
542
+ */
543
+ async deletePost(postId) {
544
+ try {
545
+ if (!postId) {
546
+ return new Error('Post ID is required');
547
+ }
548
+ // Get post to verify it exists
549
+ const post = await this.get(postId);
550
+ if (!post) {
551
+ return new Error('Post not found');
552
+ }
553
+ // Soft delete the post
554
+ const success = await this.repository.delete({
555
+ id: postId
556
+ });
557
+ if (success) {
558
+ this.logger.debug('Post deleted successfully', {
559
+ postId
560
+ });
561
+ }
562
+ return success;
563
+ } catch (error) {
564
+ this.logger.error('Error deleting post: %o', error);
565
+ return error instanceof Error ? error : new Error('Unknown error occurred while deleting post');
566
+ }
567
+ }
568
+ /**
569
+ * Sends Expo push notification for a post
570
+ *
571
+ * @description Handles push notification logic for new posts
572
+ *
573
+ * @param {any} post - The post data
574
+ * @private
575
+ */
576
+ async sendExpoNotification(post) {
577
+ try {
578
+ if (post?.props?.notificationParams && (!post?.type || post?.type !== 'ALERT')) {
579
+ await this.messengerNotificationService.sendExpoNotificationOnPost(post);
580
+ } else if (!post?.type || post?.type !== 'ALERT') {
581
+ const notificationData = {
582
+ url: config.INBOX_MESSEGE_PATH,
583
+ params: {
584
+ channelId: post?.channel,
585
+ hideTabBar: true
586
+ },
587
+ screen: 'DialogMessages',
588
+ other: {
589
+ sound: 'default'
590
+ }
591
+ };
592
+ await this.messengerNotificationService.sendExpoNotificationOnPost(post, notificationData);
593
+ }
594
+ this.logger.debug('Expo notification sent', {
595
+ postId: post?.id
596
+ });
597
+ } catch (error) {
598
+ this.logger.error('Error sending Expo notification: %o', error);
599
+ // Don't throw error as notification failure shouldn't break post creation
600
+ }
167
601
  }
168
602
  };
169
603
  PostService = PostService_1 = __decorate([__param(0, inject(SERVER_TYPES.PostRepository)), __param(1, inject(SERVER_TYPES.ChannelRepository)), __param(2, inject(SERVER_TYPES.FileInfoService)), __param(3, inject(SERVER_TYPES.MessengerNotificationService)), __param(4, inject(CommonType.MOLECULER_BROKER)), __param(5, inject('PubSub')), __param(6, inject('Logger')), __metadata("design:paramtypes", [PostRepository, ChannelRepository, Object, Object, ServiceBroker, PubSubEngine, Object])], PostService);export{PostService};//# sourceMappingURL=post-service.js.map