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