@solidxai/core 0.1.12-beta.0 → 0.1.12-beta.2

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 (147) hide show
  1. package/dist/constants/error-messages.d.ts +1 -0
  2. package/dist/constants/error-messages.d.ts.map +1 -1
  3. package/dist/constants/error-messages.js +1 -0
  4. package/dist/constants/error-messages.js.map +1 -1
  5. package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
  6. package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
  7. package/dist/dtos/create-chatter-message.dto.js +7 -1
  8. package/dist/dtos/create-chatter-message.dto.js.map +1 -1
  9. package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
  10. package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
  11. package/dist/dtos/post-chatter-message.dto.js +6 -1
  12. package/dist/dtos/post-chatter-message.dto.js.map +1 -1
  13. package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
  14. package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
  15. package/dist/dtos/update-chatter-message.dto.js +8 -1
  16. package/dist/dtos/update-chatter-message.dto.js.map +1 -1
  17. package/dist/dtos/update-chatter-note-message.dto.d.ts +1 -0
  18. package/dist/dtos/update-chatter-note-message.dto.d.ts.map +1 -1
  19. package/dist/dtos/update-chatter-note-message.dto.js +7 -1
  20. package/dist/dtos/update-chatter-note-message.dto.js.map +1 -1
  21. package/dist/entities/chatter-message.entity.d.ts +1 -0
  22. package/dist/entities/chatter-message.entity.d.ts.map +1 -1
  23. package/dist/entities/chatter-message.entity.js +5 -1
  24. package/dist/entities/chatter-message.entity.js.map +1 -1
  25. package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
  26. package/dist/helpers/solid-core-error-codes-provider.service.js +9 -0
  27. package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
  28. package/dist/interfaces/chatter-mention-notification.interface.d.ts +27 -0
  29. package/dist/interfaces/chatter-mention-notification.interface.d.ts.map +1 -0
  30. package/dist/interfaces/chatter-mention-notification.interface.js +3 -0
  31. package/dist/interfaces/chatter-mention-notification.interface.js.map +1 -0
  32. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts +17 -0
  33. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts.map +1 -0
  34. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js +106 -0
  35. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js.map +1 -0
  36. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts +12 -0
  37. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts.map +1 -0
  38. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js +39 -0
  39. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js.map +1 -0
  40. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts +8 -0
  41. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts.map +1 -0
  42. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js +10 -0
  43. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js.map +1 -0
  44. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts +20 -0
  45. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts.map +1 -0
  46. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js +48 -0
  47. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js.map +1 -0
  48. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts +12 -0
  49. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts.map +1 -0
  50. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js +39 -0
  51. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js.map +1 -0
  52. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts +8 -0
  53. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts.map +1 -0
  54. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js +10 -0
  55. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js.map +1 -0
  56. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts +18 -0
  57. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts.map +1 -0
  58. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js +45 -0
  59. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js.map +1 -0
  60. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts +12 -0
  61. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts.map +1 -0
  62. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js +39 -0
  63. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js.map +1 -0
  64. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts +8 -0
  65. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts.map +1 -0
  66. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js +10 -0
  67. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js.map +1 -0
  68. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts +18 -0
  69. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts.map +1 -0
  70. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js +45 -0
  71. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js.map +1 -0
  72. package/dist/seeders/seed-data/solid-core-metadata.json +21 -0
  73. package/dist/services/chatter-message.service.d.ts +7 -1
  74. package/dist/services/chatter-message.service.d.ts.map +1 -1
  75. package/dist/services/chatter-message.service.js +85 -4
  76. package/dist/services/chatter-message.service.js.map +1 -1
  77. package/dist/solid-core.module.d.ts.map +1 -1
  78. package/dist/solid-core.module.js +14 -0
  79. package/dist/solid-core.module.js.map +1 -1
  80. package/dist-tests/api/authenticate.spec.js +119 -0
  81. package/dist-tests/api/authenticate.spec.js.map +1 -0
  82. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  83. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  84. package/dist-tests/api/ping.spec.js +21 -0
  85. package/dist-tests/api/ping.spec.js.map +1 -0
  86. package/dist-tests/helpers/auth.js +41 -0
  87. package/dist-tests/helpers/auth.js.map +1 -0
  88. package/dist-tests/helpers/env.js +11 -0
  89. package/dist-tests/helpers/env.js.map +1 -0
  90. package/docs/agent-builder/notebook-lm-prompt-for-agent-builder.md +136 -0
  91. package/docs/agent-builder/team-ready-note-agent-builder.md +305 -0
  92. package/docs/agent-hub-grooming.md +301 -0
  93. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +438 -0
  94. package/docs/dashboards/dashboard-curl-smoke-tests.txt +146 -0
  95. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +172 -0
  96. package/docs/datasource-introspection-ddl-analysis.md +326 -0
  97. package/docs/datasource-introspection-implementation-plan.md +306 -0
  98. package/docs/grouping-enhancements.md +89 -0
  99. package/docs/java-spring/README.md +3 -0
  100. package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
  101. package/docs/module-package-import-handoff.md +691 -0
  102. package/docs/seed-changes.md +65 -0
  103. package/docs/test-data-workflow.md +200 -0
  104. package/docs/type-declaration-import-issue.md +24 -0
  105. package/docs/workflow/business-automation-example-notes.md +309 -0
  106. package/docs/workflow/data-engineering-pipeline-example-notes.md +330 -0
  107. package/docs/workflow/foreach-example-notes.md +187 -0
  108. package/docs/workflow/hello-world-example-notes.md +271 -0
  109. package/docs/workflow/kestra-concepts-plugins-blueprints.md +315 -0
  110. package/docs/workflow/loop-until-example-notes.md +198 -0
  111. package/docs/workflow/microservices-and-apis-example-notes.md +264 -0
  112. package/docs/workflow/samples.md +25 -0
  113. package/docs/workflow/what-is-kestra.md +79 -0
  114. package/docs/workflow/workflow-core-module-handoff-summary.md +191 -0
  115. package/docs/workflow/workflow-module-brd.md +185 -0
  116. package/docs/workflow/workflow-module-domain-model.md +252 -0
  117. package/docs/workflow/workflow-module-metadata-dsl.md +302 -0
  118. package/docs/workflow/workflow-module-technical-spec.md +293 -0
  119. package/docs/workflow/workflow-node-type-contracts.md +635 -0
  120. package/docs/workflow/workflow-node-ui-metadata-contract.md +1262 -0
  121. package/docs/workflow/workflow-solidx-model-field-spec.md +284 -0
  122. package/package.json +1 -1
  123. package/src/constants/error-messages.ts +1 -0
  124. package/src/dtos/create-chatter-message.dto.ts +5 -0
  125. package/src/dtos/post-chatter-message.dto.ts +4 -0
  126. package/src/dtos/update-chatter-message.dto.ts +6 -0
  127. package/src/dtos/update-chatter-note-message.dto.ts +5 -0
  128. package/src/entities/chatter-message.entity.ts +3 -0
  129. package/src/helpers/solid-core-error-codes-provider.service.ts +9 -0
  130. package/src/interfaces/chatter-mention-notification.interface.ts +29 -0
  131. package/src/jobs/chatter-mention-notification-email-queue-handler.service.ts +114 -0
  132. package/src/jobs/database/chatter-mention-notification-email-publisher-database.service.ts +23 -0
  133. package/src/jobs/database/chatter-mention-notification-email-queue-options-database.ts +9 -0
  134. package/src/jobs/database/chatter-mention-notification-email-subscriber-database.service.ts +32 -0
  135. package/src/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.ts +23 -0
  136. package/src/jobs/rabbitmq/chatter-mention-notification-email-queue-options.ts +9 -0
  137. package/src/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.ts +30 -0
  138. package/src/jobs/redis/chatter-mention-notification-email-publisher-redis.service.ts +23 -0
  139. package/src/jobs/redis/chatter-mention-notification-email-queue-options-redis.ts +9 -0
  140. package/src/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.ts +30 -0
  141. package/src/seeders/seed-data/email-templates/chatter-mention-notification.handlebars.html +200 -0
  142. package/src/seeders/seed-data/solid-core-metadata.json +21 -0
  143. package/src/services/chatter-message.service.ts +97 -2
  144. package/src/solid-core.module.ts +14 -0
  145. package/.claude/settings.local.json +0 -16
  146. package/CLAUDE.md +0 -26
  147. package/src/services/1.js +0 -6
@@ -0,0 +1,23 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
3
+ import { QueuesModuleOptions } from 'src/interfaces';
4
+ import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
5
+ import { MqMessageService } from 'src/services/mq-message.service';
6
+ import { RedisPublisher } from 'src/services/queues/redis-publisher.service';
7
+ import queueOptions from './chatter-mention-notification-email-queue-options-redis';
8
+
9
+ @Injectable()
10
+ export class ChatterMentionNotificationEmailQueuePublisherRedis extends RedisPublisher<ChatterMentionNotificationPayload> {
11
+ constructor(
12
+ protected readonly mqMessageService: MqMessageService,
13
+ protected readonly mqMessageQueueService: MqMessageQueueService,
14
+ ) {
15
+ super(mqMessageService, mqMessageQueueService);
16
+ }
17
+
18
+ options(): QueuesModuleOptions {
19
+ return {
20
+ ...queueOptions
21
+ };
22
+ }
23
+ }
@@ -0,0 +1,9 @@
1
+ import { BrokerType } from "src/interfaces";
2
+
3
+ const QUEUE_NAME = 'solid_chatter_mention_notification_email_queue_redis';
4
+
5
+ export default {
6
+ name: QUEUE_NAME,
7
+ type: BrokerType.Redis,
8
+ queueName: QUEUE_NAME,
9
+ };
@@ -0,0 +1,30 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { ChatterMentionNotificationEmailQueueHandler } from 'src/jobs/chatter-mention-notification-email-queue-handler.service';
3
+ import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
4
+ import { QueuesModuleOptions } from 'src/interfaces';
5
+ import { QueueMessage } from 'src/interfaces/mq';
6
+ import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
7
+ import { MqMessageService } from 'src/services/mq-message.service';
8
+ import { RedisSubscriber } from 'src/services/queues/redis-subscriber.service';
9
+ import queueOptions from './chatter-mention-notification-email-queue-options-redis';
10
+
11
+ @Injectable()
12
+ export class ChatterMentionNotificationEmailQueueSubscriberRedis extends RedisSubscriber<ChatterMentionNotificationPayload> {
13
+ constructor(
14
+ readonly mqMessageService: MqMessageService,
15
+ readonly mqMessageQueueService: MqMessageQueueService,
16
+ private readonly handler: ChatterMentionNotificationEmailQueueHandler,
17
+ ) {
18
+ super(mqMessageService, mqMessageQueueService);
19
+ }
20
+
21
+ options(): QueuesModuleOptions {
22
+ return {
23
+ ...queueOptions
24
+ };
25
+ }
26
+
27
+ subscribe(message: QueueMessage<ChatterMentionNotificationPayload>) {
28
+ return this.handler.handle(message);
29
+ }
30
+ }
@@ -0,0 +1,200 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <title>You were mentioned in a note</title>
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+
9
+ <style>
10
+ @import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700&display=swap");
11
+
12
+ body {
13
+ margin: 0;
14
+ padding: 0;
15
+ background-color: #f4f4f7;
16
+ font-family: "Nunito Sans", Helvetica, Arial, sans-serif;
17
+ color: #333;
18
+ }
19
+
20
+ .email-wrapper {
21
+ max-width: 600px;
22
+ margin: 0 auto;
23
+ padding: 20px;
24
+ }
25
+
26
+ .logo {
27
+ text-align: center;
28
+ margin-bottom: 20px;
29
+ }
30
+
31
+ .logo img {
32
+ height: 50px;
33
+ }
34
+
35
+ .content-box {
36
+ background-color: #ffffff;
37
+ padding: 40px;
38
+ border-radius: 8px;
39
+ }
40
+
41
+ .title {
42
+ font-size: 22px;
43
+ margin-bottom: 10px;
44
+ }
45
+
46
+ .intro {
47
+ font-size: 16px;
48
+ line-height: 1.6;
49
+ margin: 0;
50
+ }
51
+
52
+ .note-box {
53
+ background-color: #f7f3ff;
54
+ border-left: 4px solid #722ED1;
55
+ padding: 16px;
56
+ border-radius: 5px;
57
+ margin: 24px 0;
58
+ }
59
+
60
+ .note-label {
61
+ margin: 0 0 8px;
62
+ font-size: 13px;
63
+ font-weight: 700;
64
+ color: #722ED1;
65
+ text-transform: uppercase;
66
+ letter-spacing: 0.04em;
67
+ }
68
+
69
+ .note-box p {
70
+ margin: 0;
71
+ font-size: 16px;
72
+ line-height: 1.6;
73
+ white-space: pre-wrap;
74
+ }
75
+
76
+ .note-body {
77
+ font-weight: 700;
78
+ font-style: italic;
79
+ color: #2f2450;
80
+ }
81
+
82
+ .record-summary {
83
+ background-color: #fbfbfd;
84
+ border: 1px solid #ececf1;
85
+ padding: 14px;
86
+ border-radius: 5px;
87
+ margin-bottom: 24px;
88
+ }
89
+
90
+ .record-summary p {
91
+ margin: 0 0 8px;
92
+ font-size: 14px;
93
+ line-height: 1.5;
94
+ }
95
+
96
+ .button-container {
97
+ text-align: center;
98
+ margin-bottom: 30px;
99
+ margin-top: 20px;
100
+ }
101
+
102
+ .button {
103
+ display: inline-block;
104
+ padding: 12px 24px;
105
+ background-color: #722ED1;
106
+ color: #ffffff;
107
+ text-decoration: none;
108
+ font-weight: bold;
109
+ border-radius: 5px;
110
+ }
111
+
112
+ .footer-text {
113
+ font-size: 16px;
114
+ line-height: 1.6;
115
+ }
116
+
117
+ .footer {
118
+ text-align: center;
119
+ font-size: 12px;
120
+ color: #6b6e76;
121
+ margin-top: 40px;
122
+ }
123
+
124
+ @media only screen and (max-width: 600px) {
125
+ .email-wrapper {
126
+ width: 100% !important;
127
+ padding: 20px 0 !important;
128
+ margin: 0;
129
+ }
130
+
131
+ .content-box {
132
+ padding: 20px !important;
133
+ border-radius: 0;
134
+ }
135
+
136
+ .title {
137
+ font-size: 18px !important;
138
+ }
139
+
140
+ .button {
141
+ padding: 10px !important;
142
+ font-size: 14px;
143
+ }
144
+ }
145
+ </style>
146
+ </head>
147
+
148
+ <body>
149
+ <div class="email-wrapper">
150
+ {{#if companyLogoUrl}}
151
+ <div class="logo">
152
+ <img src="{{companyLogoUrl}}" alt="Company Logo" />
153
+ </div>
154
+ {{/if}}
155
+
156
+ <div class="content-box">
157
+ <h2 class="title">Hi {{ mentionedUserDisplayName }},</h2>
158
+ <p class="intro">
159
+ <strong>{{ mentionedByDisplayName }}</strong> mentioned you in a note on
160
+ <strong>{{ entityDisplayName }}</strong>{{#if entityUserKey}} <strong>{{ entityUserKey }}</strong>{{/if}}.
161
+ </p>
162
+
163
+ <div class="note-box">
164
+ <p class="note-label" style="margin: 0 0 8px; font-size: 13px; font-weight: 700; color: #722ED1; text-transform: uppercase; letter-spacing: 0.04em;">
165
+ Note
166
+ </p>
167
+ <p class="note-body" style="margin: 0; font-size: 16px; line-height: 1.6; white-space: pre-wrap; font-weight: 700; font-style: italic; color: #2f2450;">
168
+ {{ noteBody }}
169
+ </p>
170
+ </div>
171
+
172
+ <div class="record-summary">
173
+ <p><strong>Record:</strong> {{ entityDisplayName }}{{#if entityUserKey}} - {{ entityUserKey }}{{/if}}</p>
174
+ <p><strong>Mentioned by:</strong> {{ mentionedByDisplayName }}{{#if mentionedByEmail}} ({{ mentionedByEmail }}){{/if}}</p>
175
+ </div>
176
+
177
+ <p class="intro">
178
+ To view the note and reply to {{ mentionedByDisplayName }}, open the record below.
179
+ </p>
180
+
181
+ <div class="button-container">
182
+ <a href="{{ entityFormUrl }}" class="button" target="_blank">
183
+ Open Record
184
+ </a>
185
+ </div>
186
+
187
+ <p class="intro">
188
+ Regards,
189
+ <br />
190
+ The {{ solidAppName }} Team.
191
+ </p>
192
+ </div>
193
+
194
+ <div class="footer">
195
+ © 2025 <a href="{{ solidAppWebsiteUrl }}" target="_blank">{{ solidAppName }}</a>. All rights reserved.
196
+ </div>
197
+ </div>
198
+ </body>
199
+
200
+ </html>
@@ -3911,6 +3911,18 @@
3911
3911
  "encrypt": false,
3912
3912
  "isSystem": false
3913
3913
  },
3914
+ {
3915
+ "name": "messageBodyMentions",
3916
+ "displayName": "Message Body Mentions",
3917
+ "type": "longText",
3918
+ "ormType": "text",
3919
+ "required": false,
3920
+ "unique": false,
3921
+ "index": false,
3922
+ "private": false,
3923
+ "encrypt": false,
3924
+ "isSystem": false
3925
+ },
3914
3926
  {
3915
3927
  "name": "coModelEntityId",
3916
3928
  "displayName": "CoModel Entity Id",
@@ -14461,6 +14473,15 @@
14461
14473
  "description": "Welcome email sent to users after signup.",
14462
14474
  "active": true,
14463
14475
  "type": "text"
14476
+ },
14477
+ {
14478
+ "name": "chatter-mention-notification",
14479
+ "displayName": "Default: Chatter Mention Notification",
14480
+ "body": "chatter-mention-notification.handlebars.html",
14481
+ "subject": "{{mentionedByDisplayName}} mentioned you in {{entityDisplayName}}",
14482
+ "description": "This template notifies users when they are mentioned in a custom chatter note.",
14483
+ "active": true,
14484
+ "type": "text"
14464
14485
  }
14465
14486
  ],
14466
14487
  "smsTemplates": [
@@ -11,6 +11,7 @@ import { PostChatterMessageDto } from 'src/dtos/post-chatter-message.dto';
11
11
  import { UpdateChatterNoteMessageDto } from 'src/dtos/update-chatter-note-message.dto';
12
12
  import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
13
13
  import { lowerFirst } from 'src/helpers/string.helper';
14
+ import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
14
15
  import { ChatterMessageDetailsRepository } from 'src/repository/chatter-message-details.repository';
15
16
  import { ChatterMessageRepository } from 'src/repository/chatter-message.repository';
16
17
  import { FieldMetadataRepository } from 'src/repository/field-metadata.repository';
@@ -24,6 +25,14 @@ import { getMediaStorageProvider } from './mediaStorageProviders';
24
25
  import { RequestContextService } from './request-context.service';
25
26
  import { Logger } from '@nestjs/common';
26
27
  import { SolidIntrospectService } from './solid-introspect.service';
28
+ import { PublisherFactory } from './queues/publisher-factory.service';
29
+
30
+ interface ChatterMention {
31
+ username: string;
32
+ display_name?: string;
33
+ displayName?: string;
34
+ id?: string | number;
35
+ }
27
36
 
28
37
  @Injectable()
29
38
  export class ChatterMessageService extends CRUDService<ChatterMessage> {
@@ -47,6 +56,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
47
56
  private readonly modelMetadataRepo: ModelMetadataRepository,
48
57
  readonly requestContextService: RequestContextService,
49
58
  private readonly modelMetadataHelperService: ModelMetadataHelperService,
59
+ private readonly publisherFactory: PublisherFactory<ChatterMentionNotificationPayload>,
50
60
  ) {
51
61
  super(entityManager, repo, 'chatterMessage', 'solid-core', moduleRef);
52
62
  }
@@ -106,6 +116,78 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
106
116
  .filter(v => Number.isInteger(v) && v > 0);
107
117
  }
108
118
 
119
+ private parseMessageBodyMentions(value?: string): ChatterMention[] {
120
+ if (!value || typeof value !== 'string') return [];
121
+ try {
122
+ const parsed = JSON.parse(value);
123
+ return Array.isArray(parsed) ? parsed : [];
124
+ } catch {
125
+ return [];
126
+ }
127
+ }
128
+
129
+ private renderMentionTokens(messageBody: string, mentions: ChatterMention[]) {
130
+ return mentions.reduce((nextMessage, mention, index) => {
131
+ const username = mention.username;
132
+ if (!username) return nextMessage;
133
+ return nextMessage.replace(new RegExp(`\\{\\{\\s*${index}\\s*\\}\\}`, 'g'), `@${username}`);
134
+ }, messageBody || '');
135
+ }
136
+
137
+ private async publishChatterMentionNotifications(message: ChatterMessage, model: any) {
138
+ if (message.messageType !== CHATTER_MESSAGE_TYPE.CUSTOM || message.messageSubType !== CHATTER_MESSAGE_SUBTYPE.NOTE) {
139
+ return;
140
+ }
141
+
142
+ const mentions = this.parseMessageBodyMentions(message.messageBodyMentions);
143
+ const mentionUserIds = mentions
144
+ .map(mention => Number(mention.id))
145
+ .filter(id => Number.isInteger(id) && id > 0);
146
+ const uniqueMentionUserIds = Array.from(new Set(mentionUserIds));
147
+ if (uniqueMentionUserIds.length === 0) return;
148
+
149
+ const activeUser = this.requestContextService.getActiveUser();
150
+
151
+ const payload: ChatterMentionNotificationPayload = {
152
+ templateName: 'chatter-mention-notification',
153
+ mentions: mentions.map(mention => ({
154
+ id: Number(mention.id) || undefined,
155
+ username: mention.username,
156
+ displayName: mention.display_name || mention.displayName || mention.username,
157
+ })),
158
+ actor: {
159
+ id: activeUser?.sub,
160
+ username: activeUser?.username,
161
+ email: activeUser?.email,
162
+ },
163
+ noteBody: this.renderMentionTokens(message.messageBody, mentions),
164
+ entity: {
165
+ id: message.coModelEntityId,
166
+ modelName: model?.singularName || message.coModelName,
167
+ moduleName: model?.module?.name,
168
+ displayName: model?.displayName || message.coModelName,
169
+ userKey: message.modelUserKey,
170
+ },
171
+ parentEntity: 'chatterMessage',
172
+ parentEntityId: message.id,
173
+ };
174
+
175
+ try {
176
+ await this.publisherFactory.publish(
177
+ {
178
+ payload,
179
+ parentEntity: 'chatterMessage',
180
+ parentEntityId: message.id,
181
+ retryCount: 3,
182
+ retryInterval: 5000,
183
+ },
184
+ 'ChatterMentionNotificationEmailQueuePublisher',
185
+ );
186
+ } catch (error: any) {
187
+ this._logger.error(`Failed to publish chatter mention notification email job: ${error.message}`, error.stack);
188
+ }
189
+ }
190
+
109
191
  async markCompleted(id: number) {
110
192
  const activeUser = this.requestContextService.getActiveUser();
111
193
  if (!activeUser) {
@@ -146,10 +228,11 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
146
228
 
147
229
  const removeAttachmentIds = this.parseAttachmentIds(updateDto?.removeAttachmentIds);
148
230
  const hasMessageBody = typeof updateDto?.messageBody === 'string';
231
+ const hasMessageBodyMentions = typeof updateDto?.messageBodyMentions === 'string';
149
232
  const trimmedMessageBody = (updateDto?.messageBody ?? '').trim();
150
233
  const hasNewFiles = Array.isArray(files) && files.length > 0;
151
234
 
152
- if (!hasMessageBody && removeAttachmentIds.length === 0 && !hasNewFiles) {
235
+ if (!hasMessageBody && !hasMessageBodyMentions && removeAttachmentIds.length === 0 && !hasNewFiles) {
153
236
  throw new BadRequestException('No note changes submitted.');
154
237
  }
155
238
 
@@ -160,6 +243,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
160
243
  if (hasMessageBody) {
161
244
  message.messageBody = trimmedMessageBody;
162
245
  }
246
+ if (hasMessageBodyMentions) {
247
+ message.messageBodyMentions = updateDto.messageBodyMentions;
248
+ }
249
+ const model = await this.modelMetadataRepo.findOne({
250
+ where: { singularName: message.coModelName },
251
+ relations: { module: true }
252
+ });
163
253
  message.updatedBy = activeUser.sub;
164
254
  // Ensure updatedAt changes even for attachment-only edits.
165
255
  message.updatedAt = new Date();
@@ -214,6 +304,8 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
214
304
  }
215
305
  }
216
306
 
307
+ await this.publishChatterMentionNotifications(savedMessage, model);
308
+
217
309
  return savedMessage;
218
310
  }
219
311
 
@@ -226,13 +318,14 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
226
318
  chatterMessage.messageSubType = postDto.messageSubType || CHATTER_MESSAGE_SUBTYPE.CUSTOM;
227
319
  chatterMessage.status = postDto.status ?? CHATTER_MESSAGE_STATUS.PENDING;
228
320
  chatterMessage.messageBody = postDto.messageBody;
321
+ chatterMessage.messageBodyMentions = postDto.messageBodyMentions;
229
322
  chatterMessage.coModelEntityId = postDto.coModelEntityId;
230
323
  chatterMessage.coModelName = coModelName;
231
324
  chatterMessage.modelUserKey = postDto.modelUserKey ?? null;
232
325
 
233
326
  const model = await this.modelMetadataRepo.findOne({
234
327
  where: { singularName: coModelName },
235
- relations: { userKeyField: true }
328
+ relations: { userKeyField: true, module: true }
236
329
  });
237
330
  chatterMessage.modelDisplayName = model?.displayName ?? null;
238
331
 
@@ -262,6 +355,8 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
262
355
  }
263
356
  }
264
357
 
358
+ await this.publishChatterMentionNotifications(savedMessage, model);
359
+
265
360
  return savedMessage;
266
361
  }
267
362
 
@@ -130,10 +130,17 @@ import { ChatterQueuePublisherRabbitmq } from "./jobs/rabbitmq/chatter-queue-pub
130
130
  import { ChatterQueueSubscriberRabbitmq } from "./jobs/rabbitmq/chatter-queue-subscriber.service";
131
131
  import { ChatterQueuePublisherDatabase } from "./jobs/database/chatter-queue-publisher-database.service";
132
132
  import { ChatterQueueSubscriberDatabase } from "./jobs/database/chatter-queue-subscriber-database.service";
133
+ import { ChatterMentionNotificationEmailQueueHandler } from "./jobs/chatter-mention-notification-email-queue-handler.service";
134
+ import { ChatterMentionNotificationEmailQueuePublisherDatabase } from "./jobs/database/chatter-mention-notification-email-publisher-database.service";
135
+ import { ChatterMentionNotificationEmailQueueSubscriberDatabase } from "./jobs/database/chatter-mention-notification-email-subscriber-database.service";
136
+ import { ChatterMentionNotificationEmailQueuePublisherRabbitmq } from "./jobs/rabbitmq/chatter-mention-notification-email-publisher.service";
137
+ import { ChatterMentionNotificationEmailQueueSubscriberRabbitmq } from "./jobs/rabbitmq/chatter-mention-notification-email-subscriber.service";
133
138
  import { ApiEmailQueuePublisherRedis } from "./jobs/redis/api-email-publisher-redis.service";
134
139
  import { ApiEmailQueueSubscriberRedis } from "./jobs/redis/api-email-subscriber-redis.service";
135
140
  import { ChatterQueuePublisherRedis } from "./jobs/redis/chatter-queue-publisher-redis.service";
136
141
  import { ChatterQueueSubscriberRedis } from "./jobs/redis/chatter-queue-subscriber-redis.service";
142
+ import { ChatterMentionNotificationEmailQueuePublisherRedis } from "./jobs/redis/chatter-mention-notification-email-publisher-redis.service";
143
+ import { ChatterMentionNotificationEmailQueueSubscriberRedis } from "./jobs/redis/chatter-mention-notification-email-subscriber-redis.service";
137
144
  import { ComputedFieldEvaluationPublisherRedis } from "./jobs/redis/computed-field-evaluation-publisher-redis.service";
138
145
  import { ComputedFieldEvaluationSubscriberRedis } from "./jobs/redis/computed-field-evaluation-subscriber-redis.service";
139
146
  import { GenerateCodePublisherRedis } from "./jobs/redis/generate-code-publisher-redis.service";
@@ -665,6 +672,11 @@ import { PostgresDatasourceIntrospectionProviderService } from "./services/datas
665
672
  ChatterQueueSubscriberRabbitmq,
666
673
  ChatterQueuePublisherDatabase,
667
674
  ChatterQueueSubscriberDatabase,
675
+ ChatterMentionNotificationEmailQueueHandler,
676
+ ChatterMentionNotificationEmailQueuePublisherRabbitmq,
677
+ ChatterMentionNotificationEmailQueueSubscriberRabbitmq,
678
+ ChatterMentionNotificationEmailQueuePublisherDatabase,
679
+ ChatterMentionNotificationEmailQueueSubscriberDatabase,
668
680
 
669
681
  TestQueuePublisherDatabase,
670
682
  TestQueueSubscriberDatabase,
@@ -674,6 +686,8 @@ import { PostgresDatasourceIntrospectionProviderService } from "./services/datas
674
686
  ApiEmailQueueSubscriberRedis,
675
687
  ChatterQueuePublisherRedis,
676
688
  ChatterQueueSubscriberRedis,
689
+ ChatterMentionNotificationEmailQueuePublisherRedis,
690
+ ChatterMentionNotificationEmailQueueSubscriberRedis,
677
691
  ComputedFieldEvaluationPublisherRedis,
678
692
  ComputedFieldEvaluationSubscriberRedis,
679
693
  GenerateCodePublisherRedis,
@@ -1,16 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(node -e:*)",
5
- "WebFetch(domain:docs.solidxai.com)",
6
- "WebFetch(domain:github.com)",
7
- "Read(//Users/oswald/projects/Solid_Starters/solidctl/**)",
8
- "Read(//Users/oswald/projects/Solid_Starters/**)",
9
- "Bash(find /Users/oswald/projects/Solid_Starters/solid-core-module -type d -name migration* -o -name *database*)",
10
- "Bash(node verify-imports.js)"
11
- ],
12
- "additionalDirectories": [
13
- "/Users/oswald/projects/Solid_Starters/solidctl"
14
- ]
15
- }
16
- }
package/CLAUDE.md DELETED
@@ -1,26 +0,0 @@
1
- # This is the SolidX API project.
2
- This is included as a dependency in consuming projects.
3
-
4
- # SolidX UI
5
- # The corresponding UI project is at the below path:
6
- /Users/oswald/projects/Solid_Starters/solid-core-ui
7
-
8
- # SolidX Docs
9
- # The documentation project is at the below path:
10
- /Users/oswald/projects/solidxai-docs
11
-
12
- # SolidX Agent
13
- # The agent project which has the skills for helping users configure, build and use SolidX is at the below path:
14
- /Users/oswald/projects/Solid_Starters/agent
15
-
16
- # SolidX Control Plane Commands
17
- # The control plane commands for managing SolidX instances are in the below path:
18
- /Users/oswald/projects/Solid_Starters/solidctl
19
-
20
- # Testing reference project
21
- # This is the reference library management project that is used for testing and development of SolidX features. It is located at the below path:
22
- /Users/oswald/projects/Solid_Starters/solid-library-management
23
-
24
- # Code Builder project
25
- # This is the project that contains the code builder which generates code based on user input and templates. It is located at the below path:
26
- /Users/oswald/projects/Solid_Starters/solid-code-builder
package/src/services/1.js DELETED
@@ -1,6 +0,0 @@
1
- 1. Do i need to create a storeStreams method for aws service too?
2
- - Handle later
3
- 2. queues handling -> if queues is enabled by default, i.e triggerExport(exportTransactionEntity.id).
4
- - startExport should either return the data or return the transaction id
5
- 3. How to handle scenarios wherein, nested related exist.(do i need to only get the userkey)
6
- - show the userKey