@futdevpro/nts-dynamo 1.15.2 → 1.15.5

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 (192) hide show
  1. package/.cursor/rules/__assistant_guide.mdc +30 -0
  2. package/.cursor/rules/__main.mdc +64 -0
  3. package/.cursor/rules/_ag_backend-structure.mdc +86 -0
  4. package/.cursor/rules/_ag_backend.mdc +16 -0
  5. package/.cursor/rules/_ag_debug.mdc +8 -0
  6. package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -0
  7. package/.cursor/rules/_ag_file-refactoring.mdc +113 -0
  8. package/.cursor/rules/_ag_fixes_rules.mdc +6 -0
  9. package/.cursor/rules/_ag_frontend-structure.mdc +87 -0
  10. package/.cursor/rules/_ag_frontend.mdc +40 -0
  11. package/.cursor/rules/_ag_import-rules.mdc +45 -0
  12. package/.cursor/rules/_ag_naming.mdc +116 -0
  13. package/.cursor/rules/_ag_running_commands.mdc +5 -0
  14. package/.cursor/rules/_ag_server-controller.mdc +6 -0
  15. package/.cursor/rules/_ag_should-be.mdc +7 -0
  16. package/.cursor/rules/_ag_swearing.mdc +47 -0
  17. package/.cursor/rules/ai_development_guide.md +61 -0
  18. package/.cursor/rules/ai_directives.md +114 -0
  19. package/.cursor/rules/cursor-rules.md +160 -0
  20. package/.cursor/rules/default-command.mdc +465 -0
  21. package/.cursor/rules/error_code_pattern.md +40 -0
  22. package/.cursor/rules/saved rule mcp server use.md +16 -0
  23. package/_specifications/BACKLOG.md +15 -0
  24. package/_specifications/TODO.md +15 -0
  25. package/build/_modules/ai/_models/ai-test-generation-result.interface.d.ts +17 -0
  26. package/build/_modules/ai/_models/ai-test-generation-result.interface.d.ts.map +1 -0
  27. package/build/_modules/ai/_models/ai-test-generation-result.interface.js +3 -0
  28. package/build/_modules/ai/_models/ai-test-generation-result.interface.js.map +1 -0
  29. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.d.ts +36 -0
  30. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.d.ts.map +1 -0
  31. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.js +118 -0
  32. package/build/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.js.map +1 -0
  33. package/build/_modules/ai/_modules/anthropic/index.d.ts +3 -0
  34. package/build/_modules/ai/_modules/anthropic/index.d.ts.map +1 -0
  35. package/build/_modules/ai/_modules/anthropic/index.js +8 -0
  36. package/build/_modules/ai/_modules/anthropic/index.js.map +1 -0
  37. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.d.ts +35 -0
  38. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.d.ts.map +1 -0
  39. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.js +129 -0
  40. package/build/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.js.map +1 -0
  41. package/build/_modules/ai/_modules/fdp-ai/index.d.ts +3 -0
  42. package/build/_modules/ai/_modules/fdp-ai/index.d.ts.map +1 -0
  43. package/build/_modules/ai/_modules/fdp-ai/index.js +8 -0
  44. package/build/_modules/ai/_modules/fdp-ai/index.js.map +1 -0
  45. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.d.ts +40 -0
  46. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.d.ts.map +1 -0
  47. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.js +111 -0
  48. package/build/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.js.map +1 -0
  49. package/build/_modules/ai/_modules/open-ai/index.d.ts +1 -0
  50. package/build/_modules/ai/_modules/open-ai/index.d.ts.map +1 -1
  51. package/build/_modules/ai/_modules/open-ai/index.js +1 -0
  52. package/build/_modules/ai/_modules/open-ai/index.js.map +1 -1
  53. package/build/_modules/ai/_services/ai-user-key.service-base.d.ts +45 -0
  54. package/build/_modules/ai/_services/ai-user-key.service-base.d.ts.map +1 -0
  55. package/build/_modules/ai/_services/ai-user-key.service-base.js +15 -0
  56. package/build/_modules/ai/_services/ai-user-key.service-base.js.map +1 -0
  57. package/build/_modules/ai/index.d.ts +2 -0
  58. package/build/_modules/ai/index.d.ts.map +1 -1
  59. package/build/_modules/ai/index.js +2 -0
  60. package/build/_modules/ai/index.js.map +1 -1
  61. package/build/_modules/custom-data/custom-data.controller.d.ts.map +1 -1
  62. package/build/_modules/custom-data/custom-data.controller.js +1 -2
  63. package/build/_modules/custom-data/custom-data.controller.js.map +1 -1
  64. package/build/_modules/socket/app-extended.server.js +1 -1
  65. package/build/_modules/socket/app-extended.server.js.map +1 -1
  66. package/build/_services/base/data.service.d.ts +1 -1
  67. package/build/_services/base/data.service.js +1 -1
  68. package/build/_services/base/db.service.d.ts +1 -1
  69. package/build/_services/base/db.service.js +1 -1
  70. package/build/_services/core/api.service.d.ts.map +1 -1
  71. package/build/_services/core/api.service.js +1 -0
  72. package/build/_services/core/api.service.js.map +1 -1
  73. package/build/_services/core/auth.service.d.ts +2 -2
  74. package/build/_services/core/auth.service.js +1 -1
  75. package/build/_services/core/email.service.js +1 -1
  76. package/build/_services/core/email.service.js.map +1 -1
  77. package/build/_services/core/global.service.d.ts +1 -1
  78. package/build/_services/core/global.service.js +2 -2
  79. package/build/_services/core/global.service.js.map +1 -1
  80. package/build/_services/server/app.server.d.ts.map +1 -1
  81. package/build/_services/server/app.server.js +11 -1
  82. package/build/_services/server/app.server.js.map +1 -1
  83. package/package.json +18 -4
  84. package/scripts/run-coverage-tests.js +5 -1
  85. package/spec/support/helpers/spec-reporter-loader.js +359 -0
  86. package/spec/support/helpers/ts-node-helper.js +84 -0
  87. package/spec/support/jasmine.coverage.json +2 -1
  88. package/spec/support/jasmine.json +3 -3
  89. package/src/_collections/archive.util.spec.ts +36 -0
  90. package/src/_collections/get-environment-settings.util.spec.ts +210 -0
  91. package/src/_collections/star.controller.spec.ts +224 -0
  92. package/src/_models/control-models/api-call-params.control-model.spec.ts +62 -3
  93. package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -0
  94. package/src/_models/control-models/app-params.control-model.spec.ts +158 -2
  95. package/src/_models/control-models/endpoint-params.control-model.spec.ts +578 -0
  96. package/src/_modules/ai/_models/ai-test-generation-result.interface.ts +16 -0
  97. package/src/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.ts +138 -0
  98. package/src/_modules/ai/_modules/anthropic/index.ts +5 -0
  99. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -0
  100. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -0
  101. package/src/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.ts +189 -0
  102. package/src/_modules/ai/_modules/fdp-ai/index.ts +5 -0
  103. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -0
  104. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -0
  105. package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +240 -0
  106. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -0
  107. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +437 -0
  108. package/src/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.ts +157 -0
  109. package/src/_modules/ai/_modules/open-ai/index.ts +1 -0
  110. package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -0
  111. package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -0
  112. package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -0
  113. package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +79 -0
  114. package/src/_modules/ai/_services/ai-user-key.service-base.ts +59 -0
  115. package/src/_modules/ai/index.ts +2 -0
  116. package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -0
  117. package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -0
  118. package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -0
  119. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -0
  120. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -0
  121. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -0
  122. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -0
  123. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -0
  124. package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -0
  125. package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -0
  126. package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -0
  127. package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -0
  128. package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -0
  129. package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -0
  130. package/src/_modules/custom-data/custom-data.controller.ts +1 -3
  131. package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -0
  132. package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -0
  133. package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -0
  134. package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -0
  135. package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -0
  136. package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -0
  137. package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -0
  138. package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -0
  139. package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -0
  140. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -0
  141. package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -0
  142. package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -0
  143. package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -0
  144. package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -0
  145. package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -0
  146. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -0
  147. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +345 -0
  148. package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -0
  149. package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -0
  150. package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -0
  151. package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -0
  152. package/src/_modules/mock/data-model.mock.spec.ts +27 -24
  153. package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -0
  154. package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -0
  155. package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -0
  156. package/src/_modules/server/errors/errors.control-service.spec.ts +230 -0
  157. package/src/_modules/server/errors/errors.controller.spec.ts +165 -0
  158. package/src/_modules/server/errors/errors.data-service.spec.ts +355 -0
  159. package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -0
  160. package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -0
  161. package/src/_modules/server/server-status/server-status.control-service.spec.ts +516 -0
  162. package/src/_modules/server/server-status/server-status.controller.spec.ts +156 -0
  163. package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +6 -3
  164. package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -0
  165. package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -0
  166. package/src/_modules/socket/app-extended.server.ts +1 -1
  167. package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -0
  168. package/src/_modules/test/test.controller.spec.ts +72 -0
  169. package/src/_modules/usage/usage.controller.spec.ts +81 -0
  170. package/src/_modules/usage/usage.data-service.spec.ts +332 -0
  171. package/src/_services/base/api.service-base.spec.ts +125 -0
  172. package/src/_services/base/archive-data.service.spec.ts +196 -0
  173. package/src/_services/base/data.service.spec.ts +493 -0
  174. package/src/_services/base/data.service.ts +1 -1
  175. package/src/_services/base/db.service.spec.ts +59 -18
  176. package/src/_services/base/db.service.ts +1 -1
  177. package/src/_services/base/singleton.service-base.spec.ts +28 -0
  178. package/src/_services/base/singleton.service.spec.ts +114 -0
  179. package/src/_services/core/api.service.ts +1 -0
  180. package/src/_services/core/auth.service.spec.ts +159 -0
  181. package/src/_services/core/auth.service.ts +2 -2
  182. package/src/_services/core/email.service.spec.ts +14 -22
  183. package/src/_services/core/email.service.ts +1 -1
  184. package/src/_services/core/global.service.spec.ts +275 -0
  185. package/src/_services/core/global.service.ts +2 -2
  186. package/src/_services/core/service-collection.service.spec.ts +46 -0
  187. package/src/_services/route/controller.service.ts +1 -1
  188. package/src/_services/route/routing-module.service.spec.ts +8 -6
  189. package/src/_services/server/app.server.ts +17 -1
  190. package/src/_services/shared.static-service.spec.ts +89 -0
  191. package/src/_modules/socket/app-extended.server.spec.ts +0 -227
  192. package/src/_services/server/app.server.spec.ts +0 -138
@@ -0,0 +1,219 @@
1
+
2
+ import { DyNTS_Msg_Events_Service } from './msg-events.service';
3
+ import { DyFM_Msg_EventKey } from '@futdevpro/fsm-dynamo/messaging';
4
+ import { DyFM_Log } from '@futdevpro/fsm-dynamo';
5
+
6
+ describe('| DyNTS_Msg_Events_Service', () => {
7
+ let service: DyNTS_Msg_Events_Service;
8
+ let mockSocketServer: any;
9
+
10
+ beforeEach(() => {
11
+ service = DyNTS_Msg_Events_Service.getInstance();
12
+ mockSocketServer = {
13
+ emitToRoom: jasmine.createSpy('emitToRoom'),
14
+ emitToUser: jasmine.createSpy('emitToUser'),
15
+ };
16
+ spyOn(service, 'getSocketServer' as any).and.returnValue(mockSocketServer);
17
+ });
18
+
19
+ it('| should be a singleton instance', () => {
20
+ const instance1 = DyNTS_Msg_Events_Service.getInstance();
21
+ const instance2 = DyNTS_Msg_Events_Service.getInstance();
22
+
23
+ expect(instance1).toBe(instance2);
24
+ expect(instance1).toBeInstanceOf(DyNTS_Msg_Events_Service);
25
+ });
26
+
27
+ describe('| emitMessageSent', () => {
28
+ it('| should emit message sent event to conversation room', () => {
29
+ const message = { _id: 'msg-123', content: 'Test message' };
30
+
31
+ service.emitMessageSent(message, 'conv-123');
32
+
33
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
34
+ 'conversation:conv-123',
35
+ DyFM_Msg_EventKey.messageSent,
36
+ message
37
+ );
38
+ });
39
+
40
+ it('| should handle error gracefully when socket server is not available', () => {
41
+ (service as any).getSocketServer = jasmine.createSpy('getSocketServer').and.returnValue(null);
42
+ const logSpy = spyOn(DyFM_Log, 'error');
43
+
44
+ service.emitMessageSent({}, 'conv-123');
45
+
46
+ expect(logSpy).not.toHaveBeenCalled();
47
+ });
48
+ });
49
+
50
+ describe('| emitMessageUpdated', () => {
51
+ it('| should emit message updated event', () => {
52
+ const message = { _id: 'msg-123', content: 'Updated message' };
53
+
54
+ service.emitMessageUpdated(message, 'conv-123');
55
+
56
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
57
+ 'conversation:conv-123',
58
+ DyFM_Msg_EventKey.messageUpdated,
59
+ message
60
+ );
61
+ });
62
+ });
63
+
64
+ describe('| emitTypingIndicator', () => {
65
+ it('| should emit typing start event', () => {
66
+ service.emitTypingIndicator('user-123', 'conv-123', true);
67
+
68
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
69
+ 'conversation:conv-123',
70
+ DyFM_Msg_EventKey.typingStart,
71
+ { userId: 'user-123', conversationId: 'conv-123' }
72
+ );
73
+ });
74
+
75
+ it('| should emit typing stop event', () => {
76
+ service.emitTypingIndicator('user-123', 'conv-123', false);
77
+
78
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
79
+ 'conversation:conv-123',
80
+ DyFM_Msg_EventKey.typingStop,
81
+ { userId: 'user-123', conversationId: 'conv-123' }
82
+ );
83
+ });
84
+ });
85
+
86
+ describe('| emitConversationCreated', () => {
87
+ it('| should emit conversation created event to all participants', () => {
88
+ const conversation = { _id: 'conv-123', name: 'Test Conversation' };
89
+ const participantIds = ['user-1', 'user-2', 'user-3'];
90
+
91
+ service.emitConversationCreated(conversation, participantIds);
92
+
93
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledTimes(3);
94
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
95
+ 'user-1',
96
+ DyFM_Msg_EventKey.conversationCreated,
97
+ conversation
98
+ );
99
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
100
+ 'user-2',
101
+ DyFM_Msg_EventKey.conversationCreated,
102
+ conversation
103
+ );
104
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
105
+ 'user-3',
106
+ DyFM_Msg_EventKey.conversationCreated,
107
+ conversation
108
+ );
109
+ });
110
+ });
111
+
112
+ describe('| emitMessageDeleted', () => {
113
+ it('| should emit message deleted event', () => {
114
+ service.emitMessageDeleted('msg-123', 'conv-123');
115
+
116
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
117
+ 'conversation:conv-123',
118
+ DyFM_Msg_EventKey.messageDeleted,
119
+ { messageId: 'msg-123', conversationId: 'conv-123' }
120
+ );
121
+ });
122
+ });
123
+
124
+ describe('| emitConversationUpdated', () => {
125
+ it('| should emit conversation updated event to all participants', () => {
126
+ const conversation = {
127
+ _id: 'conv-123',
128
+ participants: [
129
+ { userId: 'user-1' },
130
+ { userId: 'user-2' },
131
+ ],
132
+ };
133
+
134
+ service.emitConversationUpdated(conversation);
135
+
136
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledTimes(2);
137
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
138
+ 'user-1',
139
+ DyFM_Msg_EventKey.conversationUpdated,
140
+ conversation
141
+ );
142
+ });
143
+ });
144
+
145
+ describe('| emitConversationDeleted', () => {
146
+ it('| should emit conversation deleted event', () => {
147
+ service.emitConversationDeleted('conv-123');
148
+
149
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
150
+ 'conversation:conv-123',
151
+ DyFM_Msg_EventKey.conversationDeleted,
152
+ { conversationId: 'conv-123' }
153
+ );
154
+ });
155
+ });
156
+
157
+ describe('| emitParticipantAdded', () => {
158
+ it('| should emit participant added event', () => {
159
+ service.emitParticipantAdded('conv-123', 'user-456');
160
+
161
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
162
+ 'user-456',
163
+ DyFM_Msg_EventKey.participantAdded,
164
+ { conversationId: 'conv-123', userId: 'user-456' }
165
+ );
166
+ });
167
+ });
168
+
169
+ describe('| emitParticipantRemoved', () => {
170
+ it('| should emit participant removed event', () => {
171
+ service.emitParticipantRemoved('conv-123', 'user-456');
172
+
173
+ expect(mockSocketServer.emitToUser).toHaveBeenCalledWith(
174
+ 'user-456',
175
+ DyFM_Msg_EventKey.participantRemoved,
176
+ { conversationId: 'conv-123', userId: 'user-456' }
177
+ );
178
+ });
179
+ });
180
+
181
+ describe('| emitMessageRead', () => {
182
+ it('| should emit message read event', () => {
183
+ service.emitMessageRead('msg-123', 'user-456', 'conv-123');
184
+
185
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
186
+ 'conversation:conv-123',
187
+ DyFM_Msg_EventKey.messageRead,
188
+ { messageId: 'msg-123', userId: 'user-456', conversationId: 'conv-123' }
189
+ );
190
+ });
191
+ });
192
+
193
+ describe('| emitReactionAdded', () => {
194
+ it('| should emit reaction added event', () => {
195
+ const reaction = { emoji: '👍', userId: 'user-123', conversationId: 'conv-123' };
196
+
197
+ service.emitReactionAdded('msg-123', reaction);
198
+
199
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
200
+ 'conversation:conv-123',
201
+ DyFM_Msg_EventKey.reactionAdded,
202
+ { messageId: 'msg-123', reaction }
203
+ );
204
+ });
205
+ });
206
+
207
+ describe('| emitReactionRemoved', () => {
208
+ it('| should emit reaction removed event', () => {
209
+ service.emitReactionRemoved('msg-123', 'user-123', '👍');
210
+
211
+ expect(mockSocketServer.emitToRoom).toHaveBeenCalledWith(
212
+ 'conversation:user-123',
213
+ DyFM_Msg_EventKey.reactionRemoved,
214
+ { messageId: 'msg-123', userId: 'user-123', emoji: '👍' }
215
+ );
216
+ });
217
+ });
218
+ });
219
+
@@ -0,0 +1,147 @@
1
+
2
+ import { DyNTS_Msg_Main_ControlService } from './msg-main.control-service';
3
+ import { DyNTS_Msg_Events_Service } from './msg-events.service';
4
+ import { DyNTS_GlobalService } from '../../../_services/core/global.service';
5
+ import {
6
+ DyFM_Msg_Message,
7
+ DyFM_Msg_Conversation,
8
+ DyFM_Msg_Status,
9
+ DyFM_Msg_Type,
10
+ DyFM_Msg_ConversationType,
11
+ DyFM_Msg_ParticipantRole,
12
+ } from '@futdevpro/fsm-dynamo/messaging';
13
+ import { DyFM_Error, DyFM_EnvironmentFlag } from '@futdevpro/fsm-dynamo';
14
+ import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
15
+
16
+ describe('| DyNTS_Msg_Main_ControlService', () => {
17
+ let service: DyNTS_Msg_Main_ControlService;
18
+ let mockDBService: jasmine.SpyObj<any>;
19
+ let mockEventsService: jasmine.SpyObj<DyNTS_Msg_Events_Service>;
20
+
21
+ beforeAll(() => {
22
+ if (!DyNTS_global_settings.systemShortCodeName) {
23
+ (DyNTS_global_settings as any).systemShortCodeName = 'TEST';
24
+ }
25
+ if (!DyNTS_global_settings.env_settings) {
26
+ (DyNTS_global_settings as any).env_settings = { environment: DyFM_EnvironmentFlag.local };
27
+ }
28
+ });
29
+
30
+ beforeEach(() => {
31
+ mockDBService = jasmine.createSpyObj('DyNTS_DBService', [
32
+ 'getAll',
33
+ 'getDataById',
34
+ 'getDataListByIds',
35
+ 'getDataByDependencyId',
36
+ 'getDataListByDependencyIds',
37
+ 'getDataListByDependencyId',
38
+ 'findOne',
39
+ 'find',
40
+ 'updateOne',
41
+ 'createData',
42
+ 'modifyData',
43
+ 'markDeletedById',
44
+ 'trueDeleteDataById',
45
+ 'trueDeleteAllData',
46
+ 'restoreDeletedById',
47
+ ]);
48
+ mockEventsService = jasmine.createSpyObj('DyNTS_Msg_Events_Service', [
49
+ 'emitMessageSent',
50
+ 'emitMessageUpdated',
51
+ 'emitMessageDeleted',
52
+ 'emitMessageRead',
53
+ 'emitReactionAdded',
54
+ 'emitReactionRemoved',
55
+ 'emitConversationCreated',
56
+ 'emitConversationUpdated',
57
+ 'emitConversationDeleted',
58
+ 'emitParticipantAdded',
59
+ 'emitParticipantRemoved',
60
+ ]);
61
+
62
+ spyOn(DyNTS_GlobalService, 'getDBService').and.returnValue(mockDBService);
63
+ spyOn(DyNTS_GlobalService, 'getDBServiceByKey').and.returnValue(mockDBService);
64
+ spyOn(DyNTS_Msg_Events_Service, 'getInstance').and.returnValue(mockEventsService);
65
+ service = DyNTS_Msg_Main_ControlService.getInstance();
66
+ (service as any).eventsService = mockEventsService;
67
+ });
68
+
69
+ it('| should be a singleton instance', () => {
70
+ const instance1 = DyNTS_Msg_Main_ControlService.getInstance();
71
+ const instance2 = DyNTS_Msg_Main_ControlService.getInstance();
72
+
73
+ expect(instance1).toBe(instance2);
74
+ expect(instance1).toBeInstanceOf(DyNTS_Msg_Main_ControlService);
75
+ });
76
+
77
+ describe('| deleteMessage', () => {
78
+ it('| should delete a message successfully', async () => {
79
+ const mockMessage = new DyFM_Msg_Message({
80
+ _id: 'msg-123',
81
+ conversationId: 'conv-123',
82
+ senderId: 'user-123',
83
+ content: 'Test message',
84
+ type: DyFM_Msg_Type.text,
85
+ status: DyFM_Msg_Status.sent,
86
+ });
87
+ mockDBService.getDataById.and.returnValue(Promise.resolve(mockMessage));
88
+ mockDBService.markDeletedById.and.returnValue(Promise.resolve());
89
+
90
+ await service.deleteMessage('msg-123', 'user-123', 'issuer-123');
91
+
92
+ expect(mockDBService.markDeletedById).toHaveBeenCalledWith('msg-123', 'issuer-123');
93
+ expect(mockEventsService.emitMessageDeleted).toHaveBeenCalled();
94
+ });
95
+
96
+ it('| should throw error when user is not the sender', async () => {
97
+ const mockMessage = new DyFM_Msg_Message({
98
+ _id: 'msg-123',
99
+ conversationId: 'conv-123',
100
+ senderId: 'user-123',
101
+ content: 'Test message',
102
+ type: DyFM_Msg_Type.text,
103
+ status: DyFM_Msg_Status.sent,
104
+ });
105
+ mockDBService.getDataById.and.returnValue(Promise.resolve(mockMessage));
106
+
107
+ await expectAsync(
108
+ service.deleteMessage('msg-123', 'user-456', 'issuer-123')
109
+ ).toBeRejectedWith(jasmine.any(DyFM_Error));
110
+ });
111
+ });
112
+
113
+ describe('| deleteConversation', () => {
114
+ it('| should delete conversation when user is owner', async () => {
115
+ const mockConversation = new DyFM_Msg_Conversation({
116
+ _id: 'conv-123',
117
+ type: DyFM_Msg_ConversationType.direct,
118
+ participants: [
119
+ { userId: 'user-123', role: DyFM_Msg_ParticipantRole.owner, joinedAt: new Date() },
120
+ ],
121
+ });
122
+ mockDBService.getDataById.and.returnValue(Promise.resolve(mockConversation));
123
+ mockDBService.markDeletedById.and.returnValue(Promise.resolve());
124
+
125
+ await service.deleteConversation('conv-123', 'user-123', 'issuer-123');
126
+
127
+ expect(mockDBService.markDeletedById).toHaveBeenCalledWith('conv-123', 'issuer-123');
128
+ expect(mockEventsService.emitConversationDeleted).toHaveBeenCalled();
129
+ });
130
+
131
+ it('| should throw error when user is not owner or admin', async () => {
132
+ const mockConversation = new DyFM_Msg_Conversation({
133
+ _id: 'conv-123',
134
+ type: DyFM_Msg_ConversationType.direct,
135
+ participants: [
136
+ { userId: 'user-123', role: DyFM_Msg_ParticipantRole.member, joinedAt: new Date() },
137
+ ],
138
+ });
139
+ mockDBService.getDataById.and.returnValue(Promise.resolve(mockConversation));
140
+
141
+ await expectAsync(
142
+ service.deleteConversation('conv-123', 'user-123', 'issuer-123')
143
+ ).toBeRejectedWith(jasmine.any(DyFM_Error));
144
+ });
145
+ });
146
+ });
147
+
@@ -0,0 +1,201 @@
1
+
2
+ import { DyNTS_Msg_Controller } from './msg.controller';
3
+ import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo';
4
+ import { DyFM_msgModule_settings } from '@futdevpro/fsm-dynamo/messaging';
5
+ import { DyNTS_GlobalService } from '../../../_services/core/global.service';
6
+ import type { DyNTS_AuthService } from '../../../_services/core/auth.service';
7
+
8
+ describe('| DyNTS_Msg_Controller', () => {
9
+ let controller: DyNTS_Msg_Controller;
10
+ let mockAuthService: jasmine.SpyObj<{ getIssuerFromRequest: (req: unknown) => string }>;
11
+
12
+ beforeEach(() => {
13
+ mockAuthService = jasmine.createSpyObj('DyNTS_AuthService', ['getIssuerFromRequest']);
14
+ mockAuthService.getIssuerFromRequest.and.returnValue('user-123');
15
+ spyOn(DyNTS_GlobalService, 'getAuthService').and.returnValue(mockAuthService as unknown as DyNTS_AuthService);
16
+ controller = DyNTS_Msg_Controller.getInstance();
17
+ });
18
+
19
+ it('| should be a singleton instance', () => {
20
+ const instance1 = DyNTS_Msg_Controller.getInstance();
21
+ const instance2 = DyNTS_Msg_Controller.getInstance();
22
+
23
+ expect(instance1).toBe(instance2);
24
+ expect(instance1).toBeInstanceOf(DyNTS_Msg_Controller);
25
+ });
26
+
27
+ describe('| setupEndpoints', () => {
28
+ it('| should setup all messaging endpoints', () => {
29
+ controller.setupEndpoints();
30
+
31
+ expect(controller.endpoints).toBeDefined();
32
+ expect(controller.endpoints.length).toBeGreaterThanOrEqual(12);
33
+ });
34
+
35
+ it('| should setup getConversations endpoint', () => {
36
+ controller.setupEndpoints();
37
+
38
+ const getConversationsEndpoint = controller.endpoints.find(ep => ep.name === 'getConversations');
39
+ expect(getConversationsEndpoint).toBeDefined();
40
+ expect(getConversationsEndpoint?.type).toBe(DyFM_HttpCallType.get);
41
+ expect(getConversationsEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.getConversations);
42
+ expect((getConversationsEndpoint as any)?.tasks).toBeDefined();
43
+ expect((getConversationsEndpoint as any)?.tasks?.length).toBe(1);
44
+ });
45
+
46
+ it('| should setup getConversation endpoint', () => {
47
+ controller.setupEndpoints();
48
+
49
+ const getConversationEndpoint = controller.endpoints.find(ep => ep.name === 'getConversation');
50
+ expect(getConversationEndpoint).toBeDefined();
51
+ expect(getConversationEndpoint?.type).toBe(DyFM_HttpCallType.get);
52
+ expect(getConversationEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.getConversation);
53
+ expect((getConversationEndpoint as any)?.tasks).toBeDefined();
54
+ expect((getConversationEndpoint as any)?.tasks?.length).toBe(1);
55
+ });
56
+
57
+ it('| should setup createConversation endpoint', () => {
58
+ controller.setupEndpoints();
59
+
60
+ const createConversationEndpoint = controller.endpoints.find(ep => ep.name === 'createConversation');
61
+ expect(createConversationEndpoint).toBeDefined();
62
+ expect(createConversationEndpoint?.type).toBe(DyFM_HttpCallType.post);
63
+ expect(createConversationEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.createConversation);
64
+ expect((createConversationEndpoint as any)?.tasks).toBeDefined();
65
+ expect((createConversationEndpoint as any)?.tasks?.length).toBe(1);
66
+ });
67
+
68
+ it('| should setup getMessages endpoint', () => {
69
+ controller.setupEndpoints();
70
+
71
+ const getMessagesEndpoint = controller.endpoints.find(ep => ep.name === 'getMessages');
72
+ expect(getMessagesEndpoint).toBeDefined();
73
+ expect(getMessagesEndpoint?.type).toBe(DyFM_HttpCallType.get);
74
+ expect(getMessagesEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.getMessages);
75
+ expect((getMessagesEndpoint as any)?.tasks).toBeDefined();
76
+ expect((getMessagesEndpoint as any)?.tasks?.length).toBe(1);
77
+ });
78
+
79
+ it('| should setup sendMessage endpoint', () => {
80
+ controller.setupEndpoints();
81
+
82
+ const sendMessageEndpoint = controller.endpoints.find(ep => ep.name === 'sendMessage');
83
+ expect(sendMessageEndpoint).toBeDefined();
84
+ expect(sendMessageEndpoint?.type).toBe(DyFM_HttpCallType.post);
85
+ expect(sendMessageEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.sendMessage);
86
+ expect((sendMessageEndpoint as any)?.tasks).toBeDefined();
87
+ expect((sendMessageEndpoint as any)?.tasks?.length).toBe(1);
88
+ });
89
+
90
+ it('| should setup editMessage endpoint', () => {
91
+ controller.setupEndpoints();
92
+
93
+ const editMessageEndpoint = controller.endpoints.find(ep => ep.name === 'editMessage');
94
+ expect(editMessageEndpoint).toBeDefined();
95
+ expect(editMessageEndpoint?.type).toBe(DyFM_HttpCallType.patch);
96
+ expect(editMessageEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.editMessage);
97
+ expect((editMessageEndpoint as any)?.tasks).toBeDefined();
98
+ expect((editMessageEndpoint as any)?.tasks?.length).toBe(1);
99
+ });
100
+
101
+ it('| should setup deleteMessage endpoint', () => {
102
+ controller.setupEndpoints();
103
+
104
+ const deleteMessageEndpoint = controller.endpoints.find(ep => ep.name === 'deleteMessage');
105
+ expect(deleteMessageEndpoint).toBeDefined();
106
+ expect(deleteMessageEndpoint?.type).toBe(DyFM_HttpCallType.delete);
107
+ expect(deleteMessageEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.deleteMessage);
108
+ expect((deleteMessageEndpoint as any)?.tasks).toBeDefined();
109
+ expect((deleteMessageEndpoint as any)?.tasks?.length).toBe(1);
110
+ });
111
+
112
+ it('| should setup markAsRead endpoint', () => {
113
+ controller.setupEndpoints();
114
+
115
+ const markAsReadEndpoint = controller.endpoints.find(ep => ep.name === 'markAsRead');
116
+ expect(markAsReadEndpoint).toBeDefined();
117
+ expect(markAsReadEndpoint?.type).toBe(DyFM_HttpCallType.post);
118
+ expect(markAsReadEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.markAsRead);
119
+ expect((markAsReadEndpoint as any)?.tasks).toBeDefined();
120
+ expect((markAsReadEndpoint as any)?.tasks?.length).toBe(1);
121
+ });
122
+
123
+ it('| should setup addReaction endpoint', () => {
124
+ controller.setupEndpoints();
125
+
126
+ const addReactionEndpoint = controller.endpoints.find(ep => ep.name === 'addReaction');
127
+ expect(addReactionEndpoint).toBeDefined();
128
+ expect(addReactionEndpoint?.type).toBe(DyFM_HttpCallType.post);
129
+ expect(addReactionEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.addReaction);
130
+ expect((addReactionEndpoint as any)?.tasks).toBeDefined();
131
+ expect((addReactionEndpoint as any)?.tasks?.length).toBe(1);
132
+ });
133
+
134
+ it('| should setup removeReaction endpoint', () => {
135
+ controller.setupEndpoints();
136
+
137
+ const removeReactionEndpoint = controller.endpoints.find(ep => ep.name === 'removeReaction');
138
+ expect(removeReactionEndpoint).toBeDefined();
139
+ expect(removeReactionEndpoint?.type).toBe(DyFM_HttpCallType.delete);
140
+ expect(removeReactionEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.removeReaction);
141
+ expect((removeReactionEndpoint as any)?.tasks).toBeDefined();
142
+ expect((removeReactionEndpoint as any)?.tasks?.length).toBe(1);
143
+ });
144
+
145
+ it('| should setup updateConversation endpoint', () => {
146
+ controller.setupEndpoints();
147
+
148
+ const updateConversationEndpoint = controller.endpoints.find(ep => ep.name === 'updateConversation');
149
+ expect(updateConversationEndpoint).toBeDefined();
150
+ expect(updateConversationEndpoint?.type).toBe(DyFM_HttpCallType.patch);
151
+ expect(updateConversationEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.updateConversation);
152
+ expect((updateConversationEndpoint as any)?.tasks).toBeDefined();
153
+ expect((updateConversationEndpoint as any)?.tasks?.length).toBe(1);
154
+ });
155
+
156
+ it('| should setup deleteConversation endpoint', () => {
157
+ controller.setupEndpoints();
158
+
159
+ const deleteConversationEndpoint = controller.endpoints.find(ep => ep.name === 'deleteConversation');
160
+ expect(deleteConversationEndpoint).toBeDefined();
161
+ expect(deleteConversationEndpoint?.type).toBe(DyFM_HttpCallType.delete);
162
+ expect(deleteConversationEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.deleteConversation);
163
+ expect((deleteConversationEndpoint as any)?.tasks).toBeDefined();
164
+ expect((deleteConversationEndpoint as any)?.tasks?.length).toBe(1);
165
+ });
166
+
167
+ it('| should setup addParticipant endpoint', () => {
168
+ controller.setupEndpoints();
169
+
170
+ const addParticipantEndpoint = controller.endpoints.find(ep => ep.name === 'addParticipant');
171
+ expect(addParticipantEndpoint).toBeDefined();
172
+ expect(addParticipantEndpoint?.type).toBe(DyFM_HttpCallType.post);
173
+ expect(addParticipantEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.addParticipant);
174
+ expect((addParticipantEndpoint as any)?.tasks).toBeDefined();
175
+ expect((addParticipantEndpoint as any)?.tasks?.length).toBe(1);
176
+ });
177
+
178
+ it('| should setup removeParticipant endpoint', () => {
179
+ controller.setupEndpoints();
180
+
181
+ const removeParticipantEndpoint = controller.endpoints.find(ep => ep.name === 'removeParticipant');
182
+ expect(removeParticipantEndpoint).toBeDefined();
183
+ expect(removeParticipantEndpoint?.type).toBe(DyFM_HttpCallType.delete);
184
+ expect(removeParticipantEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.removeParticipant);
185
+ expect((removeParticipantEndpoint as any)?.tasks).toBeDefined();
186
+ expect((removeParticipantEndpoint as any)?.tasks?.length).toBe(1);
187
+ });
188
+
189
+ it('| should setup getAgentProcess endpoint', () => {
190
+ controller.setupEndpoints();
191
+
192
+ const getAgentProcessEndpoint = controller.endpoints.find(ep => ep.name === 'getAgentProcess');
193
+ expect(getAgentProcessEndpoint).toBeDefined();
194
+ expect(getAgentProcessEndpoint?.type).toBe(DyFM_HttpCallType.get);
195
+ expect(getAgentProcessEndpoint?.endpoint).toBe(DyFM_msgModule_settings.endPoints.getAgentProcess);
196
+ expect((getAgentProcessEndpoint as any)?.tasks).toBeDefined();
197
+ expect((getAgentProcessEndpoint as any)?.tasks?.length).toBe(1);
198
+ });
199
+ });
200
+ });
201
+
@@ -35,19 +35,19 @@ describe('| Dependency_Mock', () => {
35
35
  });
36
36
  });
37
37
 
38
- xdescribe('| DyFM_DataModel_Params for Dependency_Mock', () => {
38
+ describe('| DyFM_DataModel_Params for Dependency_Mock', () => {
39
39
  it('| should have correct dataName and properties', () => {
40
40
  expect(dependency_mock_DataParams.dataName).toBe('dependency_mock');
41
- expect(dependency_mock_DataParams.properties).toEqual({
42
- string: { type: 'string' },
43
- number: { type: 'number' },
44
- date: { type: 'Date' },
45
- boolean: { type: 'boolean' },
46
- array: { type: 'string[]' },
47
- object: { type: 'any' },
48
- objectArray: { type: 'any[]' },
49
- objectArrayArray: { type: 'any[][]' },
50
- });
41
+ // Check that required properties exist with correct type
42
+ expect(dependency_mock_DataParams.properties.string).toBeDefined();
43
+ expect(dependency_mock_DataParams.properties.string.type).toBe('string');
44
+ expect(dependency_mock_DataParams.properties.number).toBeDefined();
45
+ expect(dependency_mock_DataParams.properties.number.type).toBe('number');
46
+ expect(dependency_mock_DataParams.properties.date).toBeDefined();
47
+ // DyFM_DataModel_Params normalizes type to lowercase 'date'
48
+ expect(dependency_mock_DataParams.properties.date.type).toBe('date');
49
+ expect(dependency_mock_DataParams.properties.boolean).toBeDefined();
50
+ expect(dependency_mock_DataParams.properties.boolean.type).toBe('boolean');
51
51
  });
52
52
  });
53
53
 
@@ -85,24 +85,27 @@ describe('| Dependent_Mock', () => {
85
85
  });
86
86
  });
87
87
 
88
- xdescribe('| DyFM_DataModel_Params for Dependent_Mock', () => {
88
+ describe('| DyFM_DataModel_Params for Dependent_Mock', () => {
89
89
  it('| should have correct dataName and properties', () => {
90
90
  expect(dependent_mock_DataParams.dataName).toBe('dependent_mock');
91
- expect(dependent_mock_DataParams.properties).toEqual({
92
- dependencyId: {
91
+ // Use jasmine.objectContaining to allow for additional properties from base class
92
+ // Note: DyFM_DataModel_Params normalizes array types to 'array' and object types to 'object'
93
+ expect(dependent_mock_DataParams.properties).toEqual(jasmine.objectContaining({
94
+ dependencyId: jasmine.objectContaining({
93
95
  type: 'string',
94
96
  unique: true,
95
97
  required: true,
96
98
  dependencyDataName: dependency_mock_DataParams.dataName,
97
- },
98
- string: { type: 'string' },
99
- number: { type: 'number' },
100
- date: { type: 'Date' },
101
- boolean: { type: 'boolean' },
102
- array: { type: 'string[]' },
103
- object: { type: 'any' },
104
- objectArray: { type: 'any[]' },
105
- objectArrayArray: { type: 'any[][]' },
106
- });
99
+ }),
100
+ string: jasmine.objectContaining({ type: 'string' }),
101
+ number: jasmine.objectContaining({ type: 'number' }),
102
+ // DyFM_DataModel_Params normalizes type to lowercase 'date'
103
+ date: jasmine.objectContaining({ type: 'date' }),
104
+ boolean: jasmine.objectContaining({ type: 'boolean' }),
105
+ array: jasmine.objectContaining({ type: 'array' }),
106
+ object: jasmine.objectContaining({ type: 'object' }),
107
+ objectArray: jasmine.objectContaining({ type: 'array' }),
108
+ objectArrayArray: jasmine.objectContaining({ type: 'array' }),
109
+ }));
107
110
  });
108
111
  });