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