@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,283 +1,676 @@
1
- import {__decorate,__param,__metadata}from'tslib';import {inject}from'inversify';import {SERVER_TYPES,RoomType,SortEnum}from'common/server';import {BaseService}from'@common-stack/store-mongo';import'../constants/query.constants.js';import {DEFAULT_NOTIFY_PROPS}from'../constants/default-notify-props.js';var ChannelService_1;
2
- let ChannelService = ChannelService_1 = class ChannelService extends BaseService {
1
+ import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import {Emitter,DisposableCollection}from'@adminide-stack/core';import {SERVER_TYPES,RoomType,SortEnum}from'common/server';import {BaseService2}from'@common-stack/store-mongo';import'@cdm-logger/core';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import'../constants/query.constants.js';import {DEFAULT_NOTIFY_PROPS}from'../constants/default-notify-props.js';import {config}from'../config/env-config.js';var ChannelService_1;
2
+ /**
3
+ * Modern implementation of the Channel Service
4
+ *
5
+ * This service handles comprehensive channel management within the messenger platform,
6
+ * providing operations for managing channels, their members, and related messaging workflows.
7
+ *
8
+ * Key capabilities:
9
+ * - Channel lifecycle management (creation, updates, deletion)
10
+ * - Member management (adding, removing, role assignment)
11
+ * - Direct and public channel handling
12
+ * - Message and post management within channels
13
+ * - Channel visibility and access control
14
+ * - Notification and unread message tracking
15
+ * - Team-based channel organization
16
+ * - Channel discovery and filtering
17
+ * - Redis caching for performance optimization
18
+ * - Comprehensive error handling and logging
19
+ * - Event-driven architecture with proper disposal
20
+ *
21
+ * The service layer abstracts the underlying data access operations and
22
+ * provides a cohesive API for channel-related functionality throughout
23
+ * the messaging platform, handling complex business rules and cross-cutting concerns.
24
+ */
25
+ let ChannelService = ChannelService_1 = class ChannelService extends BaseService2 {
3
26
  repository;
4
27
  postService;
5
- constructor(repository, postService) {
28
+ broker;
29
+ redisCacheManager;
30
+ redisClient;
31
+ // Event emitters for channel lifecycle events
32
+ onChannelCreated = new Emitter();
33
+ onChannelUpdated = new Emitter();
34
+ onChannelDeleted = new Emitter();
35
+ onChannelRestored = new Emitter();
36
+ onMemberAdded = new Emitter();
37
+ onMemberRemoved = new Emitter();
38
+ onChannelViewed = new Emitter();
39
+ toDispose = new DisposableCollection(this.onChannelCreated, this.onChannelUpdated, this.onChannelDeleted, this.onChannelRestored, this.onMemberAdded, this.onMemberRemoved, this.onChannelViewed);
40
+ logger;
41
+ constructor(repository, postService, broker, redisCacheManager, redisClient, logger) {
6
42
  super(repository);
7
43
  this.repository = repository;
8
44
  this.postService = postService;
45
+ this.broker = broker;
46
+ this.redisCacheManager = redisCacheManager;
47
+ this.redisClient = redisClient;
48
+ this.logger = logger?.child({
49
+ className: 'ChannelService'
50
+ }) || console;
51
+ }
52
+ /**
53
+ * Disposes of resources used by the service
54
+ */
55
+ dispose() {
56
+ this.toDispose.dispose();
57
+ }
58
+ /**
59
+ * Helper method to make service calls
60
+ * @param command - Command to execute
61
+ * @param params - Command parameters
62
+ * @param topic - Service topic
63
+ * @param opts - Call options
64
+ * @returns Command result
65
+ */
66
+ async callAction(command, params, topic, opts) {
67
+ try {
68
+ if (!this.broker) {
69
+ throw new Error('Service broker not available');
70
+ }
71
+ const actionName = topic ? `${topic}.${command}` : command;
72
+ return await this.broker.call(actionName, params, opts);
73
+ } catch (error) {
74
+ this.logger.error(`Error calling action ${command}: %o`, error);
75
+ throw error;
76
+ }
9
77
  }
10
- async isMember(channelId, user) {
11
- const channel = await this.get(channelId);
12
- return !!channel?.members?.find(member => member.user && member.user.toString() === user.toString());
78
+ /**
79
+ * Invalidates channel cache entries
80
+ * @param channelId - Channel ID
81
+ * @param channelName - Channel name
82
+ */
83
+ async invalidateChannelCache(channelId, channelName) {
84
+ if (!this.redisCacheManager) {
85
+ return;
86
+ }
87
+ try {
88
+ // Delete ID-based cache if ID is provided
89
+ if (channelId) {
90
+ await this.redisCacheManager.del(`${config.APP_NAME}:getChannelById`, {
91
+ id: channelId
92
+ }, {
93
+ userId: 'system'
94
+ }, true);
95
+ }
96
+ // Delete name-based cache if name is provided
97
+ if (channelName) {
98
+ await this.redisCacheManager.del(`${config.APP_NAME}:getChannelByName`, {
99
+ name: channelName
100
+ }, {
101
+ userId: 'system'
102
+ }, true);
103
+ }
104
+ this.logger.debug(`Invalidated cache for channel ${channelId || channelName}`);
105
+ } catch (error) {
106
+ this.logger.warn(`Error invalidating channel cache: ${error.message}`);
107
+ }
13
108
  }
14
- static getDmNameFromIds(senderId, receiverId) {
15
- return `${senderId}__${receiverId}`;
109
+ /**
110
+ * Enhanced method to check if a user is a member of a specific channel
111
+ *
112
+ * @description Verifies channel membership with proper error handling and logging
113
+ *
114
+ * @param {string} channelId - The ID of the channel to check
115
+ * @param {string} user - The ID of the user
116
+ * @returns {Promise<boolean>} - True if the user is a member
117
+ */
118
+ async isMember(channelId, user) {
119
+ try {
120
+ if (!channelId || !user) {
121
+ this.logger.warn('Channel ID and user ID are required for membership check');
122
+ return false;
123
+ }
124
+ this.logger.debug('Checking channel membership', {
125
+ channelId,
126
+ userId: user
127
+ });
128
+ const channel = await this.get(channelId);
129
+ if (!channel?.members) {
130
+ this.logger.debug('Channel not found or has no members', {
131
+ channelId
132
+ });
133
+ return false;
134
+ }
135
+ const isMember = !!channel.members.find(member => member.user && member.user.toString() === user.toString());
136
+ this.logger.debug('Channel membership check result', {
137
+ channelId,
138
+ userId: user,
139
+ isMember
140
+ });
141
+ return isMember;
142
+ } catch (error) {
143
+ this.logger.error('Error checking channel membership: %o', error);
144
+ return false;
145
+ }
16
146
  }
147
+ /**
148
+ * Enhanced method to get default notification properties
149
+ *
150
+ * @description Retrieves default notification settings with extensibility
151
+ *
152
+ * @returns {INotificationProps} - Default notification properties
153
+ */
17
154
  get defaultNotifyProps() {
18
- // #Todo: To be moved to settings
19
- return DEFAULT_NOTIFY_PROPS;
155
+ try {
156
+ // Future enhancement: Load from user preferences or organization settings
157
+ return DEFAULT_NOTIFY_PROPS;
158
+ } catch (error) {
159
+ this.logger.error('Error getting default notification props: %o', error);
160
+ return DEFAULT_NOTIFY_PROPS;
161
+ }
20
162
  }
21
- static getMaxChannelsPerTeam(teamId) {
22
- // #Todo: Get Max Channel per team from Team settings
23
- return Promise.resolve(10);
163
+ /**
164
+ * Enhanced method to get maximum channels per team with configuration support
165
+ *
166
+ * @description Retrieves channel limit with future configuration support
167
+ *
168
+ * @param {string} teamId - The ID of the team
169
+ * @returns {Promise<number>} - Maximum number of channels allowed
170
+ */
171
+ static async getMaxChannelsPerTeam(teamId) {
172
+ try {
173
+ // Future enhancement: Get from team settings or organization configuration
174
+ return Promise.resolve(100); // Default max channels per team
175
+ } catch (error) {
176
+ console.error('Error getting max channels per team:', error);
177
+ return Promise.resolve(10); // Fallback value
178
+ }
24
179
  }
180
+ /**
181
+ * Enhanced method to get current channel count per team
182
+ *
183
+ * @description Counts active channels for a team with proper error handling
184
+ *
185
+ * @param {string} team - The team identifier
186
+ * @returns {Promise<number>} - Current channel count
187
+ */
25
188
  async getCurrentChannelCountPerTeam(team) {
26
- return this.repository.count({
27
- team,
28
- type: RoomType.Channel
29
- });
189
+ try {
190
+ if (!team) {
191
+ this.logger.warn('Team ID is required for channel count');
192
+ return 0;
193
+ }
194
+ const count = await this.repository.count({
195
+ team,
196
+ type: RoomType.Channel,
197
+ deletedAt: {
198
+ $exists: false
199
+ } // Only count non-deleted channels
200
+ });
201
+ this.logger.debug('Current channel count for team', {
202
+ team,
203
+ count
204
+ });
205
+ return count;
206
+ } catch (error) {
207
+ this.logger.error('Error getting current channel count per team: %o', error);
208
+ return 0;
209
+ }
210
+ }
211
+ /**
212
+ * Enhanced method to generate DM name from user IDs
213
+ *
214
+ * @description Creates a standardized direct message channel name
215
+ *
216
+ * @param {string} senderId - The sender's user ID
217
+ * @param {string} receiverId - The receiver's user ID
218
+ * @returns {string} - Generated DM name
219
+ */
220
+ static getDmNameFromIds(senderId, receiverId) {
221
+ try {
222
+ if (!senderId || !receiverId) {
223
+ throw new Error('Both sender and receiver IDs are required');
224
+ }
225
+ // Sort IDs to ensure consistent naming regardless of order
226
+ const [id1, id2] = [senderId, receiverId].sort();
227
+ return `${id1}__${id2}`;
228
+ } catch (error) {
229
+ console.error('Error generating DM name:', error);
230
+ return `${senderId}__${receiverId}`;
231
+ }
30
232
  }
233
+ /**
234
+ * Enhanced method to create a direct channel between users
235
+ *
236
+ * @description Creates direct channels with comprehensive validation and error handling
237
+ *
238
+ * @param {ICreateDirectChannelParams} data - The direct channel creation parameters
239
+ * @returns {Promise<AsDomainType<IChannelModel> | Error>} - The created channel or error
240
+ */
31
241
  async createDirectChannel(data) {
32
- const {
33
- sender,
34
- receiver,
35
- displayName,
36
- orgName,
37
- channelOptions
38
- } = data;
39
- const chlMember = [{
40
- user: sender,
41
- schemeAdmin: channelOptions?.schemeAdmin || false,
42
- notifyProps: this.defaultNotifyProps
43
- }];
44
- receiver.forEach(re => {
45
- if (re != sender) {
46
- chlMember.push({
47
- user: re,
48
- schemeAdmin: channelOptions?.schemeAdmin || false,
49
- notifyProps: this.defaultNotifyProps
242
+ try {
243
+ this.logger.debug('Creating direct channel', {
244
+ sender: data.sender,
245
+ receiverCount: data.receiver?.length || 0,
246
+ orgName: data.orgName
247
+ });
248
+ const {
249
+ sender,
250
+ receiver,
251
+ displayName,
252
+ orgName,
253
+ channelOptions
254
+ } = data;
255
+ if (!sender) {
256
+ return new Error('Sender ID is required');
257
+ }
258
+ if (!receiver || receiver.length === 0) {
259
+ return new Error('At least one receiver is required');
260
+ }
261
+ // Check for duplicate direct channel
262
+ const existingChannelName = ChannelService_1.getDmNameFromIds(sender, receiver[0]);
263
+ const existingChannel = await this.getByName(existingChannelName);
264
+ if (existingChannel) {
265
+ this.logger.debug('Direct channel already exists', {
266
+ channelName: existingChannelName
50
267
  });
268
+ return existingChannel;
51
269
  }
52
- });
53
- const channelPayload = {
54
- title: sender.split('').reverse().join(''),
55
- orgName,
56
- type: RoomType.Direct,
57
- creator: sender,
58
- members: chlMember,
59
- displayName
60
- };
61
- return this.saveDirectChannel(channelPayload);
270
+ // Build channel members
271
+ const channelMembers = [{
272
+ user: sender,
273
+ schemeAdmin: channelOptions?.schemeAdmin || false,
274
+ notifyProps: this.defaultNotifyProps
275
+ }];
276
+ receiver.forEach(receiverId => {
277
+ if (receiverId !== sender) {
278
+ channelMembers.push({
279
+ user: receiverId,
280
+ schemeAdmin: channelOptions?.schemeAdmin || false,
281
+ notifyProps: this.defaultNotifyProps
282
+ });
283
+ }
284
+ });
285
+ const channelPayload = {
286
+ title: displayName || ChannelService_1.getDmNameFromIds(sender, receiver[0]),
287
+ orgName,
288
+ type: RoomType.Direct,
289
+ creator: sender,
290
+ members: channelMembers,
291
+ displayName: displayName || `Direct chat`,
292
+ _id: undefined // Allow repository to generate
293
+ };
294
+ const result = await this.saveDirectChannel(channelPayload);
295
+ if (!(result instanceof Error)) {
296
+ this.onChannelCreated.fire({
297
+ channel: result,
298
+ userContext: {
299
+ accountId: sender,
300
+ tenantId: orgName
301
+ }
302
+ });
303
+ }
304
+ return result;
305
+ } catch (error) {
306
+ this.logger.error('Error creating direct channel: %o', error);
307
+ return error instanceof Error ? error : new Error('Unknown error occurred while creating direct channel');
308
+ }
62
309
  }
310
+ /**
311
+ * Enhanced method to save a direct channel
312
+ *
313
+ * @description Saves direct channels with comprehensive validation
314
+ *
315
+ * @param {ISaveDirectChannelParams} channel - The direct channel parameters
316
+ * @returns {Promise<AsDomainType<IChannelModel> | Error>} - The created channel or error
317
+ */
63
318
  async saveDirectChannel(channel) {
64
- const {
65
- type,
66
- deletedAt
67
- } = channel;
68
- if (deletedAt) {
69
- throw new Error('Deleted Channel can not be saved');
70
- }
71
- if (type !== RoomType.Direct) {
72
- throw new Error('Only direct channels are allowed');
319
+ try {
320
+ this.logger.debug('Saving direct channel', {
321
+ type: channel.type,
322
+ creator: channel.creator,
323
+ memberCount: channel.members?.length || 0
324
+ });
325
+ const {
326
+ type,
327
+ deletedAt
328
+ } = channel;
329
+ if (deletedAt) {
330
+ return new Error('Deleted channels cannot be saved');
331
+ }
332
+ if (type !== RoomType.Direct) {
333
+ return new Error('Only direct channels are allowed in this method');
334
+ }
335
+ const result = await this.repository.create(channel);
336
+ this.logger.debug('Direct channel saved successfully', {
337
+ channelId: result.id,
338
+ type: result.type
339
+ });
340
+ return result;
341
+ } catch (error) {
342
+ this.logger.error('Error saving direct channel: %o', error);
343
+ return error instanceof Error ? error : new Error('Unknown error occurred while saving direct channel');
73
344
  }
74
- return this.repository.create(channel);
75
345
  }
346
+ /**
347
+ * Enhanced method to add a member to a channel
348
+ *
349
+ * @description Adds a single member to a channel with comprehensive validation and event firing
350
+ *
351
+ * @param {string} channelId - The ID of the channel
352
+ * @param {string} memberId - The ID of the member to add
353
+ * @returns {Promise<AsDomainType<IChannelModel> | Error>} - The updated channel or error
354
+ */
76
355
  async addMemberToChannel(channelId, memberId) {
77
- // const { channelId, memberId } = data;
78
- // console.log('==============================', channelId);
79
- const resData = await this.repository.get({
80
- id: channelId
81
- }).then(async res => {
82
- const mebs = res.members;
83
- mebs.push({
84
- id: '',
85
- user: memberId,
86
- schemeAdmin: false,
87
- notifyProps: this.defaultNotifyProps
356
+ try {
357
+ this.logger.debug('Adding member to channel', {
358
+ channelId,
359
+ memberId
88
360
  });
89
- const objToUpdate = res;
90
- objToUpdate.members = mebs;
91
- const finalResult = await this.repository.update({
361
+ if (!channelId || !memberId) {
362
+ return new Error('Channel ID and member ID are required');
363
+ }
364
+ // Check if member is already in channel
365
+ const isMember = await this.isMember(channelId, memberId);
366
+ if (isMember) {
367
+ this.logger.debug('Member already exists in channel', {
368
+ channelId,
369
+ memberId
370
+ });
371
+ return await this.get(channelId);
372
+ }
373
+ const resData = await this.repository.get({
92
374
  id: channelId
93
- }, objToUpdate, {
94
- overwrite: true
95
- }).then(response => response).catch(error => error);
96
- return finalResult;
97
- }).catch(err => err);
98
- return resData;
375
+ }).then(async res => {
376
+ if (!res) {
377
+ throw new Error(`Channel ${channelId} not found`);
378
+ }
379
+ const members = res.members || [];
380
+ members.push({
381
+ user: memberId,
382
+ schemeAdmin: false,
383
+ notifyProps: this.defaultNotifyProps
384
+ });
385
+ const objToUpdate = {
386
+ ...res,
387
+ members
388
+ };
389
+ const finalResult = await this.repository.update({
390
+ id: channelId
391
+ }, objToUpdate, {
392
+ overwrite: true
393
+ });
394
+ return finalResult;
395
+ }).catch(err => {
396
+ this.logger.error('Error in addMemberToChannel operation: %o', err);
397
+ return err;
398
+ });
399
+ if (resData instanceof Error) {
400
+ return resData;
401
+ }
402
+ // Fire member added event
403
+ this.onMemberAdded.fire({
404
+ channelId,
405
+ memberId,
406
+ userContext: {
407
+ accountId: memberId
408
+ }
409
+ });
410
+ this.logger.debug('Member added to channel successfully', {
411
+ channelId,
412
+ memberId
413
+ });
414
+ return resData;
415
+ } catch (error) {
416
+ this.logger.error('Error adding member to channel: %o', error);
417
+ return error instanceof Error ? error : new Error('Unknown error occurred while adding member to channel');
418
+ }
99
419
  }
100
420
  async saveMembersToChannel(data) {
101
- const {
102
- channelId,
103
- membersIds
104
- } = data;
105
- const resData = await this.repository.get({
106
- id: channelId
107
- }).then(async res => {
108
- let mebs = res.members;
109
- if (Array.isArray(membersIds)) {
110
- if (membersIds?.length) {
111
- membersIds.forEach(mid => {
112
- mebs.push({
113
- id: '',
114
- user: mid,
115
- schemeAdmin: false,
116
- notifyProps: this.defaultNotifyProps
421
+ try {
422
+ const {
423
+ channelId,
424
+ membersIds
425
+ } = data;
426
+ const resData = await this.repository.get({
427
+ id: channelId
428
+ }).then(async res => {
429
+ let mebs = res.members || [];
430
+ if (Array.isArray(membersIds)) {
431
+ if (membersIds?.length) {
432
+ membersIds.forEach(mid => {
433
+ mebs.push({
434
+ user: mid,
435
+ schemeAdmin: false,
436
+ notifyProps: this.defaultNotifyProps
437
+ });
117
438
  });
118
- });
439
+ }
119
440
  }
441
+ const objToUpdate = res;
442
+ objToUpdate.members = mebs;
443
+ const finalResult = await this.repository.update({
444
+ id: channelId
445
+ }, objToUpdate, {
446
+ overwrite: true
447
+ });
448
+ return finalResult;
449
+ }).catch(err => err);
450
+ if (resData instanceof Error) {
451
+ return resData;
120
452
  }
121
- const objToUpdate = res;
122
- objToUpdate.members = mebs;
123
- const finalResult = await this.repository.update({
124
- id: channelId
125
- }, objToUpdate, {
126
- overwrite: true
127
- });
128
- return finalResult;
129
- }).catch(err => err);
130
- return resData;
453
+ return resData;
454
+ } catch (error) {
455
+ this.logger.error('Error saving members to channel: %o', error);
456
+ return error instanceof Error ? error : new Error('Unknown error occurred');
457
+ }
131
458
  }
132
459
  async saveChannel(data) {
133
- const {
134
- type,
135
- team,
136
- creator
137
- } = data;
138
- if (type === RoomType.Direct) {
139
- throw new Error('Invalid Channel Type');
140
- }
141
- if (team) {
142
- const maxChannels = await ChannelService_1.getMaxChannelsPerTeam(team);
143
- const currentChannels = await this.getCurrentChannelCountPerTeam(team);
144
- const canAddNewChannel = currentChannels < maxChannels;
145
- if (!canAddNewChannel) {
146
- throw Error(`Only max of ${maxChannels} allowed`);
460
+ try {
461
+ const {
462
+ type,
463
+ team,
464
+ creator
465
+ } = data;
466
+ if (type === RoomType.Direct) {
467
+ return new Error('Invalid Channel Type');
147
468
  }
469
+ if (team) {
470
+ const maxChannels = await ChannelService_1.getMaxChannelsPerTeam(team);
471
+ const currentChannels = await this.getCurrentChannelCountPerTeam(team);
472
+ const canAddNewChannel = currentChannels < maxChannels;
473
+ if (!canAddNewChannel) {
474
+ return new Error(`Only max of ${maxChannels} allowed`);
475
+ }
476
+ }
477
+ const channelPayload = {
478
+ ...data,
479
+ members: [{
480
+ user: creator,
481
+ schemeAdmin: false,
482
+ notifyProps: this.defaultNotifyProps
483
+ }]
484
+ };
485
+ const result = await this.repository.create(channelPayload);
486
+ return result;
487
+ } catch (error) {
488
+ this.logger.error('Error saving channel: %o', error);
489
+ return error instanceof Error ? error : new Error('Unknown error occurred');
148
490
  }
149
- const channelPayload = {
150
- ...data,
151
- members: [{
152
- user: creator,
153
- schemeAdmin: false,
154
- notifyProps: this.defaultNotifyProps
155
- }]
156
- };
157
- return this.repository.create(channelPayload);
158
491
  }
159
492
  async savePublicChannel(data) {
160
- const {
161
- type
162
- } = data;
163
- if (type !== RoomType.Public) {
164
- throw new Error('Invalid Channel Type');
493
+ try {
494
+ const {
495
+ type
496
+ } = data;
497
+ if (type !== RoomType.Public) {
498
+ return new Error('Invalid Channel Type');
499
+ }
500
+ const result = await this.repository.create(data);
501
+ return result;
502
+ } catch (error) {
503
+ this.logger.error('Error saving public channel: %o', error);
504
+ return error instanceof Error ? error : new Error('Unknown error occurred');
165
505
  }
166
- return this.repository.create(data);
167
506
  }
168
507
  async getChannelUnread(channelId, userId) {
169
- const channel = await this.repository.get({
170
- id: channelId,
171
- members: {
172
- user: userId
508
+ try {
509
+ const channel = await this.repository.get({
510
+ id: channelId,
511
+ members: {
512
+ user: userId
513
+ }
514
+ }); // Type assertion to handle the interface mismatch
515
+ const {
516
+ members,
517
+ team,
518
+ id
519
+ } = channel;
520
+ const member = members?.find(i => i.user && i.user.toString() === userId);
521
+ if (!member) {
522
+ return {
523
+ channelId: id,
524
+ teamId: team ? team.toString() : '',
525
+ msgCount: 0,
526
+ msgCountRoot: 0,
527
+ mentionCount: 0,
528
+ notifyProps: this.defaultNotifyProps,
529
+ mentionCountRoot: 0
530
+ };
173
531
  }
174
- });
175
- const {
176
- members,
177
- team,
178
- id
179
- } = channel;
180
- const member = members.find(i => i.user && i.user.toString() === userId);
181
- if (!member) {
532
+ const msgCount = (channel.totalMsgCount || 0) - (member.msgCount || 0);
533
+ const msgCountRoot = (channel.totalMsgCountRoot || 0) - (member.msgCountRoot || 0);
534
+ const {
535
+ notifyProps,
536
+ mentionCountRoot,
537
+ mentionCount
538
+ } = member;
182
539
  return {
183
540
  channelId: id,
184
541
  teamId: team ? team.toString() : '',
185
- msgCount: 0,
186
- msgCountRoot: 0,
187
- mentionCount: 0,
188
- notifyProps: this.defaultNotifyProps,
189
- mentionCountRoot: 0
542
+ msgCount,
543
+ msgCountRoot,
544
+ mentionCount: mentionCount || 0,
545
+ notifyProps: notifyProps || this.defaultNotifyProps,
546
+ mentionCountRoot: mentionCountRoot || 0
190
547
  };
548
+ } catch (error) {
549
+ this.logger.error('Error getting channel unread: %o', error);
550
+ return error instanceof Error ? error : new Error('Unknown error occurred');
191
551
  }
192
- const msgCount = channel.totalMsgCount - member.msgCount;
193
- const msgCountRoot = channel.totalMsgCountRoot - member.msgCountRoot;
194
- const {
195
- notifyProps,
196
- mentionCountRoot,
197
- mentionCount
198
- } = member;
199
- return {
200
- channelId: id,
201
- teamId: team ? team.toString() : '',
202
- msgCount,
203
- msgCountRoot,
204
- mentionCount,
205
- notifyProps,
206
- mentionCountRoot
207
- };
208
552
  }
209
553
  async getPinnedPosts(channelId) {
210
- const posts = await this.postService.getAll({
211
- criteria: {
212
- channelId,
213
- isPinned: true
214
- },
215
- sort: {
216
- key: 'CreatAt',
217
- value: SortEnum.Asc
218
- }
219
- });
220
- const replyCounts = await Promise.all(posts.map(post => this.postService.count({
221
- rootId: post.rootId || post.id
222
- })));
223
- return posts.reduce((acc, curr, index) => [...acc, {
224
- ...curr,
225
- replyCount: replyCounts[index]
226
- }], []);
227
- }
228
- restore(channelId, time) {
229
- return this.repository.update({
230
- id: channelId
231
- }, {
232
- deletedAt: time
233
- });
234
- }
235
- // getByName(team: string, title: string): Promise<IChannel> {
236
- // return this.get({
237
- // team,
238
- // title,
239
- // });
240
- // }
241
- getByName(title) {
242
- return this.get({
243
- title
244
- });
245
- }
246
- getByNameIncludeDeleted(team, title) {
247
- return this.get({
248
- team,
249
- title,
250
- deletedAt: true
251
- });
554
+ try {
555
+ const posts = await this.postService.getAll({
556
+ criteria: {
557
+ channelId,
558
+ isPinned: true
559
+ },
560
+ sort: {
561
+ key: 'CreatAt',
562
+ value: SortEnum.Asc
563
+ }
564
+ });
565
+ const replyCounts = await Promise.all(posts.map(post => this.postService.count({
566
+ rootId: post.rootId || post._id
567
+ })));
568
+ return posts.reduce((acc, curr, index) => [...acc, {
569
+ ...curr,
570
+ replyCount: replyCounts[index]
571
+ }], []);
572
+ } catch (error) {
573
+ this.logger.error('Error getting pinned posts: %o', error);
574
+ return error instanceof Error ? error : new Error('Unknown error occurred');
575
+ }
252
576
  }
253
- getByNames(team, titles) {
254
- return this.getAll({
255
- criteria: {
256
- team,
257
- title: {
258
- $in: titles
577
+ async getFromMaster(id) {
578
+ try {
579
+ const result = await this.get({
580
+ id
581
+ });
582
+ return result;
583
+ } catch (error) {
584
+ this.logger.error('Error getting channel from master: %o', error);
585
+ return error instanceof Error ? error : new Error('Unknown error occurred');
586
+ }
587
+ }
588
+ async restore(channelId, time) {
589
+ try {
590
+ await this.repository.update({
591
+ id: channelId
592
+ }, {
593
+ deletedAt: time
594
+ });
595
+ } catch (error) {
596
+ this.logger.error('Error restoring channel: %o', error);
597
+ throw error;
598
+ }
599
+ }
600
+ // @ts-ignore - Type compatibility issue with base class method
601
+ async getByName(title) {
602
+ try {
603
+ const result = await this.get({
604
+ title
605
+ });
606
+ // Convert AsDomainType to IChannelModel by adding _id
607
+ return {
608
+ ...result,
609
+ _id: result.id
610
+ };
611
+ } catch (error) {
612
+ this.logger.error('Error getting channel by name: %o', error);
613
+ throw error;
614
+ }
615
+ }
616
+ async getByNameIncludeDeleted(teamId, name) {
617
+ try {
618
+ const result = await this.get({
619
+ team: teamId,
620
+ title: name,
621
+ deletedAt: true
622
+ });
623
+ return result;
624
+ } catch (error) {
625
+ this.logger.error('Error getting channel by name including deleted: %o', error);
626
+ return error instanceof Error ? error : new Error('Unknown error occurred');
627
+ }
628
+ }
629
+ async getByNames(teamId, names) {
630
+ try {
631
+ const result = await this.getAll({
632
+ criteria: {
633
+ team: teamId,
634
+ title: {
635
+ $in: names
636
+ }
259
637
  }
260
- }
261
- });
638
+ });
639
+ return result;
640
+ } catch (error) {
641
+ this.logger.error('Error getting channels by names: %o', error);
642
+ return error instanceof Error ? error : new Error('Unknown error occurred');
643
+ }
262
644
  }
263
- getChannelCounts(team, user) {
264
- return this.count({
265
- team,
266
- members: {
267
- user
268
- }
269
- });
645
+ async getChannelCounts(teamId, userId) {
646
+ try {
647
+ return await this.count({
648
+ team: teamId,
649
+ members: {
650
+ user: userId
651
+ }
652
+ });
653
+ } catch (error) {
654
+ this.logger.error('Error getting channel counts: %o', error);
655
+ return error instanceof Error ? error : new Error('Unknown error occurred');
656
+ }
270
657
  }
271
- getChannels(team, user, includeDeleted, lastDeleteAt, orgName) {
272
- return this.repository.getAll({
273
- criteria: this.generateCriteria({
274
- team,
275
- user,
276
- includeDeleted,
277
- lastDeleteAt,
278
- orgName
279
- })
280
- });
658
+ async getChannels(teamId, userId, includeDeleted, lastDeleteAt, orgId) {
659
+ try {
660
+ const result = await this.repository.getAll({
661
+ criteria: this.generateCriteria({
662
+ team: teamId,
663
+ user: userId,
664
+ includeDeleted,
665
+ lastDeleteAt,
666
+ orgName: orgId
667
+ })
668
+ });
669
+ return result;
670
+ } catch (error) {
671
+ this.logger.error('Error getting channels: %o', error);
672
+ return error instanceof Error ? error : new Error('Unknown error occurred');
673
+ }
281
674
  }
282
675
  generateCriteria(options) {
283
676
  const {
@@ -334,72 +727,164 @@ let ChannelService = ChannelService_1 = class ChannelService extends BaseService
334
727
  }
335
728
  return criteria;
336
729
  }
337
- deleteChannel(id) {
338
- return this.repository.delete({
339
- id
340
- });
341
- }
342
- getDeleted(teamId, offset, limit, userId) {
343
- return Promise.resolve(undefined);
344
- }
345
- getDeletedByName(teamId, name) {
346
- return Promise.resolve(undefined);
730
+ async deleteChannel(id) {
731
+ try {
732
+ return await this.repository.delete({
733
+ id
734
+ });
735
+ } catch (error) {
736
+ this.logger.error('Error deleting channel: %o', error);
737
+ return error instanceof Error ? error : new Error('Unknown error occurred');
738
+ }
347
739
  }
348
- getFromMaster(id) {
349
- return Promise.resolve(undefined);
740
+ async getDeleted(teamId, offset, limit, userId) {
741
+ try {
742
+ // Implementation would go here to get deleted channels
743
+ return [];
744
+ } catch (error) {
745
+ this.logger.error('Error getting deleted channels: %o', error);
746
+ return error instanceof Error ? error : new Error('Unknown error occurred');
747
+ }
350
748
  }
351
- getMoreChannels(teamId, userId, offset, limit) {
352
- return Promise.resolve(undefined);
749
+ async getDeletedByName(teamId, name) {
750
+ try {
751
+ // Implementation would go here
752
+ return null;
753
+ } catch (error) {
754
+ this.logger.error('Error getting deleted channel by name: %o', error);
755
+ return error instanceof Error ? error : new Error('Unknown error occurred');
756
+ }
353
757
  }
354
- getPrivateChannelsForTeam(teamId, offset, limit) {
355
- return Promise.resolve(undefined);
758
+ async getMoreChannels(teamId, userId, offset, limit) {
759
+ try {
760
+ // Implementation would go here
761
+ return [];
762
+ } catch (error) {
763
+ this.logger.error('Error getting more channels: %o', error);
764
+ return error instanceof Error ? error : new Error('Unknown error occurred');
765
+ }
356
766
  }
357
- getPublicChannelsByIdsForTeam(teamId, channelsIds) {
358
- return Promise.resolve(undefined);
767
+ async getPrivateChannelsForTeam(teamId, offset, limit) {
768
+ try {
769
+ // Implementation would go here
770
+ return [];
771
+ } catch (error) {
772
+ this.logger.error('Error getting private channels for team: %o', error);
773
+ return error instanceof Error ? error : new Error('Unknown error occurred');
774
+ }
359
775
  }
360
- getPublicChannelsForTeam(teamId, offset, limit) {
361
- return Promise.resolve(undefined);
776
+ async getPublicChannelsByIdsForTeam(teamId, channelsIds) {
777
+ try {
778
+ // Implementation would go here
779
+ return [];
780
+ } catch (error) {
781
+ this.logger.error('Error getting public channels by IDs for team: %o', error);
782
+ return error instanceof Error ? error : new Error('Unknown error occurred');
783
+ }
362
784
  }
363
- getTeamChannels(teamId) {
364
- return Promise.resolve(undefined);
785
+ async getPublicChannelsForTeam(teamId, offset, limit) {
786
+ try {
787
+ // Implementation would go here
788
+ return [];
789
+ } catch (error) {
790
+ this.logger.error('Error getting public channels for team: %o', error);
791
+ return error instanceof Error ? error : new Error('Unknown error occurred');
792
+ }
365
793
  }
366
- hideChannel(id) {
367
- return Promise.resolve(false);
794
+ async getTeamChannels(teamId) {
795
+ try {
796
+ // Implementation would go here
797
+ return [];
798
+ } catch (error) {
799
+ this.logger.error('Error getting team channels: %o', error);
800
+ return error instanceof Error ? error : new Error('Unknown error occurred');
801
+ }
368
802
  }
369
- invalidateChannelByName(teamId, name) {
370
- return Promise.resolve();
803
+ async hideChannel(id) {
804
+ try {
805
+ // Implementation would go here
806
+ return false;
807
+ } catch (error) {
808
+ this.logger.error('Error hiding channel: %o', error);
809
+ return false;
810
+ }
371
811
  }
372
- leaveChannel(id) {
373
- return Promise.resolve(false);
812
+ async leaveChannel(id) {
813
+ try {
814
+ // Implementation would go here
815
+ return false;
816
+ } catch (error) {
817
+ this.logger.error('Error leaving channel: %o', error);
818
+ return false;
819
+ }
374
820
  }
375
821
  async viewChannel(id, user) {
376
- // Accessing private property
377
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
378
- // @ts-ignore
379
- if (id) {
380
- await this.repository.model.updateOne({
381
- _id: id
382
- }, {
383
- 'members.$[elem].lastViewedAt': new Date()
384
- }, {
385
- arrayFilters: [{
386
- 'elem.user': user
387
- }]
388
- });
822
+ try {
823
+ // Accessing private property
824
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
825
+ // @ts-ignore
826
+ if (id) {
827
+ await this.repository.model.updateOne({
828
+ _id: id
829
+ }, {
830
+ 'members.$[elem].lastViewedAt': new Date()
831
+ }, {
832
+ arrayFilters: [{
833
+ 'elem.user': user
834
+ }]
835
+ });
836
+ }
837
+ return true;
838
+ } catch (error) {
839
+ this.logger.error('Error viewing channel: %o', error);
840
+ return false;
841
+ }
842
+ }
843
+ async permanentDelete(channelId) {
844
+ try {
845
+ // Implementation would go here for permanent deletion
846
+ this.logger.debug(`Permanently deleting channel ${channelId}`);
847
+ } catch (error) {
848
+ this.logger.error('Error permanently deleting channel: %o', error);
849
+ return error instanceof Error ? error : new Error('Unknown error occurred');
389
850
  }
390
- return true;
391
851
  }
392
- permanentDelete(channelId) {
393
- return undefined;
852
+ async permanentDeleteByTeam(teamId) {
853
+ try {
854
+ // Implementation would go here for permanent team deletion
855
+ this.logger.debug(`Permanently deleting all channels for team ${teamId}`);
856
+ } catch (error) {
857
+ this.logger.error('Error permanently deleting channels by team: %o', error);
858
+ return error instanceof Error ? error : new Error('Unknown error occurred');
859
+ }
394
860
  }
395
- permanentDeleteByTeam(teamId) {
396
- return undefined;
861
+ async permanentDeleteMembersByChannel(channelId) {
862
+ try {
863
+ // Implementation would go here for permanent member deletion
864
+ this.logger.debug(`Permanently deleting all members for channel ${channelId}`);
865
+ } catch (error) {
866
+ this.logger.error('Error permanently deleting members by channel: %o', error);
867
+ return error instanceof Error ? error : new Error('Unknown error occurred');
868
+ }
397
869
  }
398
- permanentDeleteMembersByChannel(channelId) {
399
- return undefined;
870
+ async saveMultipleMembers(members) {
871
+ try {
872
+ // Implementation would go here
873
+ return [];
874
+ } catch (error) {
875
+ this.logger.error('Error saving multiple members: %o', error);
876
+ return error instanceof Error ? error : new Error('Unknown error occurred');
877
+ }
400
878
  }
401
- saveMultipleMembers(members) {
402
- return Promise.resolve(undefined);
879
+ async invalidateChannelByName(teamId, name) {
880
+ try {
881
+ // Implementation for cache invalidation would go here
882
+ this.logger.debug(`Invalidating channel cache for team ${teamId}, channel ${name}`);
883
+ } catch (error) {
884
+ this.logger.error('Error invalidating channel cache: %o', error);
885
+ }
403
886
  }
404
887
  };
405
- ChannelService = ChannelService_1 = __decorate([__param(0, inject(SERVER_TYPES.ChannelRepository)), __param(1, inject(SERVER_TYPES.PostService)), __metadata("design:paramtypes", [Object, Object])], ChannelService);export{ChannelService};//# sourceMappingURL=channel-service.js.map
888
+ ChannelService = ChannelService_1 = __decorate([injectable()
889
+ // @ts-ignore - Type compatibility issue between BaseService2 and IChannelService
890
+ , __param(0, inject(SERVER_TYPES.ChannelRepository)), __param(1, inject(SERVER_TYPES.PostService)), __param(2, inject(CommonType.MOLECULER_BROKER)), __param(3, inject(SERVER_TYPES.IRedisCacheManager)), __param(4, inject(CommonType.REDIS_CLIENT)), __param(5, inject('Logger')), __metadata("design:paramtypes", [Object, Object, ServiceBroker, Object, Function, Object])], ChannelService);export{ChannelService};//# sourceMappingURL=channel-service.js.map