@solidxai/core 0.1.2 → 0.1.4

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 (281) hide show
  1. package/dist/commands/run-tests.command.d.ts +37 -0
  2. package/dist/commands/run-tests.command.d.ts.map +1 -0
  3. package/dist/commands/run-tests.command.js +345 -0
  4. package/dist/commands/run-tests.command.js.map +1 -0
  5. package/dist/commands/test-data.command.d.ts +6 -6
  6. package/dist/commands/test-data.command.d.ts.map +1 -1
  7. package/dist/commands/test-data.command.js +25 -25
  8. package/dist/commands/test-data.command.js.map +1 -1
  9. package/dist/commands/test.command.d.ts +5 -0
  10. package/dist/commands/test.command.d.ts.map +1 -0
  11. package/dist/commands/test.command.js +26 -0
  12. package/dist/commands/test.command.js.map +1 -0
  13. package/dist/controllers/service.controller.d.ts +0 -9
  14. package/dist/controllers/service.controller.d.ts.map +1 -1
  15. package/dist/controllers/service.controller.js +0 -45
  16. package/dist/controllers/service.controller.js.map +1 -1
  17. package/dist/dtos/basic-filters.dto.d.ts.map +1 -1
  18. package/dist/dtos/basic-filters.dto.js.map +1 -1
  19. package/dist/dtos/create-user.dto.d.ts +1 -0
  20. package/dist/dtos/create-user.dto.d.ts.map +1 -1
  21. package/dist/dtos/create-user.dto.js +2 -1
  22. package/dist/dtos/create-user.dto.js.map +1 -1
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +3 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  28. package/dist/seeders/module-metadata-seeder.service.js +1 -20
  29. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  30. package/dist/seeders/module-test-data.service.d.ts.map +1 -1
  31. package/dist/seeders/module-test-data.service.js +3 -3
  32. package/dist/seeders/module-test-data.service.js.map +1 -1
  33. package/dist/services/chatter-message.service.d.ts +2 -0
  34. package/dist/services/chatter-message.service.d.ts.map +1 -1
  35. package/dist/services/chatter-message.service.js +18 -2
  36. package/dist/services/chatter-message.service.js.map +1 -1
  37. package/dist/services/crud.service.d.ts.map +1 -1
  38. package/dist/services/crud.service.js.map +1 -1
  39. package/dist/services/queues/common.d.ts +3 -0
  40. package/dist/services/queues/common.d.ts.map +1 -0
  41. package/dist/services/queues/common.js +39 -0
  42. package/dist/services/queues/common.js.map +1 -0
  43. package/dist/services/queues/database-publisher.service.d.ts.map +1 -1
  44. package/dist/services/queues/database-publisher.service.js +3 -1
  45. package/dist/services/queues/database-publisher.service.js.map +1 -1
  46. package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
  47. package/dist/services/queues/database-subscriber.service.js +5 -2
  48. package/dist/services/queues/database-subscriber.service.js.map +1 -1
  49. package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
  50. package/dist/services/queues/rabbitmq-publisher.service.js +13 -6
  51. package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
  52. package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
  53. package/dist/services/queues/rabbitmq-subscriber.service.js +9 -5
  54. package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
  55. package/dist/solid-core.module.d.ts.map +1 -1
  56. package/dist/solid-core.module.js +4 -0
  57. package/dist/solid-core.module.js.map +1 -1
  58. package/dist/testing/__examples__/register-example-specs.d.ts +3 -0
  59. package/dist/testing/__examples__/register-example-specs.d.ts.map +1 -0
  60. package/dist/testing/__examples__/register-example-specs.js +8 -0
  61. package/dist/testing/__examples__/register-example-specs.js.map +1 -0
  62. package/dist/testing/__examples__/specs/custom-health.spec.d.ts +17 -0
  63. package/dist/testing/__examples__/specs/custom-health.spec.d.ts.map +1 -0
  64. package/dist/testing/__examples__/specs/custom-health.spec.js +30 -0
  65. package/dist/testing/__examples__/specs/custom-health.spec.js.map +1 -0
  66. package/dist/testing/adapters/api/api-adapter.d.ts +9 -0
  67. package/dist/testing/adapters/api/api-adapter.d.ts.map +1 -0
  68. package/dist/testing/adapters/api/api-adapter.js +76 -0
  69. package/dist/testing/adapters/api/api-adapter.js.map +1 -0
  70. package/dist/testing/adapters/api/api.types.d.ts +14 -0
  71. package/dist/testing/adapters/api/api.types.d.ts.map +1 -0
  72. package/dist/testing/adapters/api/api.types.js +3 -0
  73. package/dist/testing/adapters/api/api.types.js.map +1 -0
  74. package/dist/testing/adapters/ui/playwright-adapter.d.ts +14 -0
  75. package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -0
  76. package/dist/testing/adapters/ui/playwright-adapter.js +47 -0
  77. package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -0
  78. package/dist/testing/adapters/ui/ui.types.d.ts +5 -0
  79. package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -0
  80. package/dist/testing/adapters/ui/ui.types.js +3 -0
  81. package/dist/testing/adapters/ui/ui.types.js.map +1 -0
  82. package/dist/testing/contracts/runtime-context.types.d.ts +35 -0
  83. package/dist/testing/contracts/runtime-context.types.d.ts.map +1 -0
  84. package/dist/testing/contracts/runtime-context.types.js +3 -0
  85. package/dist/testing/contracts/runtime-context.types.js.map +1 -0
  86. package/dist/testing/contracts/test-spec.types.d.ts +21 -0
  87. package/dist/testing/contracts/test-spec.types.d.ts.map +1 -0
  88. package/dist/testing/contracts/test-spec.types.js +3 -0
  89. package/dist/testing/contracts/test-spec.types.js.map +1 -0
  90. package/dist/testing/contracts/testing-metadata.types.d.ts +41 -0
  91. package/dist/testing/contracts/testing-metadata.types.d.ts.map +1 -0
  92. package/dist/testing/contracts/testing-metadata.types.js +3 -0
  93. package/dist/testing/contracts/testing-metadata.types.js.map +1 -0
  94. package/dist/testing/core/interpolation.d.ts +4 -0
  95. package/dist/testing/core/interpolation.d.ts.map +1 -0
  96. package/dist/testing/core/interpolation.js +180 -0
  97. package/dist/testing/core/interpolation.js.map +1 -0
  98. package/dist/testing/core/normalize-steps.d.ts +7 -0
  99. package/dist/testing/core/normalize-steps.d.ts.map +1 -0
  100. package/dist/testing/core/normalize-steps.js +20 -0
  101. package/dist/testing/core/normalize-steps.js.map +1 -0
  102. package/dist/testing/core/resource-store.d.ts +8 -0
  103. package/dist/testing/core/resource-store.d.ts.map +1 -0
  104. package/dist/testing/core/resource-store.js +41 -0
  105. package/dist/testing/core/resource-store.js.map +1 -0
  106. package/dist/testing/core/spec-registry.d.ts +10 -0
  107. package/dist/testing/core/spec-registry.d.ts.map +1 -0
  108. package/dist/testing/core/spec-registry.js +32 -0
  109. package/dist/testing/core/spec-registry.js.map +1 -0
  110. package/dist/testing/core/step-registry.d.ts +10 -0
  111. package/dist/testing/core/step-registry.d.ts.map +1 -0
  112. package/dist/testing/core/step-registry.js +26 -0
  113. package/dist/testing/core/step-registry.js.map +1 -0
  114. package/dist/testing/core/testing-engine.d.ts +14 -0
  115. package/dist/testing/core/testing-engine.d.ts.map +1 -0
  116. package/dist/testing/core/testing-engine.js +97 -0
  117. package/dist/testing/core/testing-engine.js.map +1 -0
  118. package/dist/testing/core/timeout.d.ts +2 -0
  119. package/dist/testing/core/timeout.d.ts.map +1 -0
  120. package/dist/testing/core/timeout.js +18 -0
  121. package/dist/testing/core/timeout.js.map +1 -0
  122. package/dist/testing/reporter/attachments.d.ts +4 -0
  123. package/dist/testing/reporter/attachments.d.ts.map +1 -0
  124. package/dist/testing/reporter/attachments.js +25 -0
  125. package/dist/testing/reporter/attachments.js.map +1 -0
  126. package/dist/testing/reporter/console-reporter.d.ts +45 -0
  127. package/dist/testing/reporter/console-reporter.d.ts.map +1 -0
  128. package/dist/testing/reporter/console-reporter.js +189 -0
  129. package/dist/testing/reporter/console-reporter.js.map +1 -0
  130. package/dist/testing/reporter/reporter.types.d.ts +37 -0
  131. package/dist/testing/reporter/reporter.types.d.ts.map +1 -0
  132. package/dist/testing/reporter/reporter.types.js +3 -0
  133. package/dist/testing/reporter/reporter.types.js.map +1 -0
  134. package/dist/testing/runner/lifecycle.d.ts +9 -0
  135. package/dist/testing/runner/lifecycle.d.ts.map +1 -0
  136. package/dist/testing/runner/lifecycle.js +33 -0
  137. package/dist/testing/runner/lifecycle.js.map +1 -0
  138. package/dist/testing/runner/run-from-metadata.d.ts +24 -0
  139. package/dist/testing/runner/run-from-metadata.d.ts.map +1 -0
  140. package/dist/testing/runner/run-from-metadata.js +70 -0
  141. package/dist/testing/runner/run-from-metadata.js.map +1 -0
  142. package/dist/testing/runner/scenario-filter.d.ts +9 -0
  143. package/dist/testing/runner/scenario-filter.d.ts.map +1 -0
  144. package/dist/testing/runner/scenario-filter.js +22 -0
  145. package/dist/testing/runner/scenario-filter.js.map +1 -0
  146. package/dist/testing/steps/api/auth.step.d.ts +3 -0
  147. package/dist/testing/steps/api/auth.step.d.ts.map +1 -0
  148. package/dist/testing/steps/api/auth.step.js +38 -0
  149. package/dist/testing/steps/api/auth.step.js.map +1 -0
  150. package/dist/testing/steps/api/index.d.ts +3 -0
  151. package/dist/testing/steps/api/index.d.ts.map +1 -0
  152. package/dist/testing/steps/api/index.js +10 -0
  153. package/dist/testing/steps/api/index.js.map +1 -0
  154. package/dist/testing/steps/api/request.step.d.ts +3 -0
  155. package/dist/testing/steps/api/request.step.d.ts.map +1 -0
  156. package/dist/testing/steps/api/request.step.js +281 -0
  157. package/dist/testing/steps/api/request.step.js.map +1 -0
  158. package/dist/testing/steps/assert/http.step.d.ts +3 -0
  159. package/dist/testing/steps/assert/http.step.d.ts.map +1 -0
  160. package/dist/testing/steps/assert/http.step.js +27 -0
  161. package/dist/testing/steps/assert/http.step.js.map +1 -0
  162. package/dist/testing/steps/assert/index.d.ts +3 -0
  163. package/dist/testing/steps/assert/index.d.ts.map +1 -0
  164. package/dist/testing/steps/assert/index.js +12 -0
  165. package/dist/testing/steps/assert/index.js.map +1 -0
  166. package/dist/testing/steps/assert/jsonpath.step.d.ts +3 -0
  167. package/dist/testing/steps/assert/jsonpath.step.d.ts.map +1 -0
  168. package/dist/testing/steps/assert/jsonpath.step.js +40 -0
  169. package/dist/testing/steps/assert/jsonpath.step.js.map +1 -0
  170. package/dist/testing/steps/assert/primitives.step.d.ts +3 -0
  171. package/dist/testing/steps/assert/primitives.step.d.ts.map +1 -0
  172. package/dist/testing/steps/assert/primitives.step.js +43 -0
  173. package/dist/testing/steps/assert/primitives.step.js.map +1 -0
  174. package/dist/testing/steps/test/index.d.ts +3 -0
  175. package/dist/testing/steps/test/index.d.ts.map +1 -0
  176. package/dist/testing/steps/test/index.js +8 -0
  177. package/dist/testing/steps/test/index.js.map +1 -0
  178. package/dist/testing/steps/test/test-spec.step.d.ts +3 -0
  179. package/dist/testing/steps/test/test-spec.step.d.ts.map +1 -0
  180. package/dist/testing/steps/test/test-spec.step.js +41 -0
  181. package/dist/testing/steps/test/test-spec.step.js.map +1 -0
  182. package/dist/testing/steps/ui/actions.step.d.ts +3 -0
  183. package/dist/testing/steps/ui/actions.step.d.ts.map +1 -0
  184. package/dist/testing/steps/ui/actions.step.js +31 -0
  185. package/dist/testing/steps/ui/actions.step.js.map +1 -0
  186. package/dist/testing/steps/ui/assertions.step.d.ts +3 -0
  187. package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -0
  188. package/dist/testing/steps/ui/assertions.step.js +41 -0
  189. package/dist/testing/steps/ui/assertions.step.js.map +1 -0
  190. package/dist/testing/steps/ui/form.step.d.ts +3 -0
  191. package/dist/testing/steps/ui/form.step.d.ts.map +1 -0
  192. package/dist/testing/steps/ui/form.step.js +34 -0
  193. package/dist/testing/steps/ui/form.step.js.map +1 -0
  194. package/dist/testing/steps/ui/index.d.ts +3 -0
  195. package/dist/testing/steps/ui/index.d.ts.map +1 -0
  196. package/dist/testing/steps/ui/index.js +14 -0
  197. package/dist/testing/steps/ui/index.js.map +1 -0
  198. package/dist/testing/steps/ui/navigation.step.d.ts +3 -0
  199. package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -0
  200. package/dist/testing/steps/ui/navigation.step.js +39 -0
  201. package/dist/testing/steps/ui/navigation.step.js.map +1 -0
  202. package/dist/testing/steps/util/index.d.ts +3 -0
  203. package/dist/testing/steps/util/index.d.ts.map +1 -0
  204. package/dist/testing/steps/util/index.js +12 -0
  205. package/dist/testing/steps/util/index.js.map +1 -0
  206. package/dist/testing/steps/util/log.step.d.ts +3 -0
  207. package/dist/testing/steps/util/log.step.d.ts.map +1 -0
  208. package/dist/testing/steps/util/log.step.js +18 -0
  209. package/dist/testing/steps/util/log.step.js.map +1 -0
  210. package/dist/testing/steps/util/require.step.d.ts +3 -0
  211. package/dist/testing/steps/util/require.step.d.ts.map +1 -0
  212. package/dist/testing/steps/util/require.step.js +16 -0
  213. package/dist/testing/steps/util/require.step.js.map +1 -0
  214. package/dist/testing/steps/util/sleep.step.d.ts +3 -0
  215. package/dist/testing/steps/util/sleep.step.d.ts.map +1 -0
  216. package/dist/testing/steps/util/sleep.step.js +13 -0
  217. package/dist/testing/steps/util/sleep.step.js.map +1 -0
  218. package/docs/test-data-workflow.md +51 -11
  219. package/package.json +4 -2
  220. package/src/commands/run-tests.command.ts +278 -0
  221. package/src/commands/test-data.command.ts +26 -26
  222. package/src/commands/test.command.ts +14 -0
  223. package/src/controllers/service.controller.ts +58 -59
  224. package/src/dtos/basic-filters.dto.ts +0 -2
  225. package/src/dtos/create-user.dto.ts +1 -0
  226. package/src/index.ts +3 -0
  227. package/src/seeders/module-metadata-seeder.service.ts +3 -24
  228. package/src/seeders/module-test-data.service.ts +5 -3
  229. package/src/services/chatter-message.service.ts +18 -1
  230. package/src/services/crud.service.ts +1 -0
  231. package/src/services/queues/common.ts +75 -0
  232. package/src/services/queues/database-publisher.service.ts +4 -1
  233. package/src/services/queues/database-subscriber.service.ts +5 -3
  234. package/src/services/queues/rabbitmq-publisher.service.ts +17 -7
  235. package/src/services/queues/rabbitmq-subscriber.service.ts +9 -5
  236. package/src/solid-core.module.ts +4 -0
  237. package/src/testing/README.md +364 -0
  238. package/src/testing/__examples__/register-example-specs.ts +6 -0
  239. package/src/testing/__examples__/specs/custom-health.spec.ts +29 -0
  240. package/src/testing/__examples__/testing.sample.json +82 -0
  241. package/src/testing/adapters/api/api-adapter.ts +85 -0
  242. package/src/testing/adapters/api/api.types.ts +15 -0
  243. package/src/testing/adapters/ui/playwright-adapter.ts +54 -0
  244. package/src/testing/adapters/ui/ui.types.ts +4 -0
  245. package/src/testing/contracts/runtime-context.types.ts +36 -0
  246. package/src/testing/contracts/test-spec.types.ts +24 -0
  247. package/src/testing/contracts/testing-metadata.types.ts +46 -0
  248. package/src/testing/core/interpolation.ts +189 -0
  249. package/src/testing/core/normalize-steps.ts +21 -0
  250. package/src/testing/core/resource-store.ts +38 -0
  251. package/src/testing/core/spec-registry.ts +33 -0
  252. package/src/testing/core/step-registry.ts +27 -0
  253. package/src/testing/core/testing-engine.ts +127 -0
  254. package/src/testing/core/timeout.ts +19 -0
  255. package/src/testing/reporter/attachments.ts +25 -0
  256. package/src/testing/reporter/console-reporter.ts +229 -0
  257. package/src/testing/reporter/reporter.types.ts +36 -0
  258. package/src/testing/runner/lifecycle.ts +31 -0
  259. package/src/testing/runner/run-from-metadata.ts +87 -0
  260. package/src/testing/runner/scenario-filter.ts +33 -0
  261. package/src/testing/steps/api/auth.step.ts +66 -0
  262. package/src/testing/steps/api/index.ts +10 -0
  263. package/src/testing/steps/api/request.step.ts +358 -0
  264. package/src/testing/steps/assert/http.step.ts +33 -0
  265. package/src/testing/steps/assert/index.ts +12 -0
  266. package/src/testing/steps/assert/jsonpath.step.ts +50 -0
  267. package/src/testing/steps/assert/primitives.step.ts +69 -0
  268. package/src/testing/steps/test/index.ts +8 -0
  269. package/src/testing/steps/test/test-spec.step.ts +52 -0
  270. package/src/testing/steps/ui/actions.step.ts +36 -0
  271. package/src/testing/steps/ui/assertions.step.ts +54 -0
  272. package/src/testing/steps/ui/form.step.ts +39 -0
  273. package/src/testing/steps/ui/index.ts +12 -0
  274. package/src/testing/steps/ui/navigation.step.ts +53 -0
  275. package/src/testing/steps/util/index.ts +10 -0
  276. package/src/testing/steps/util/log.step.ts +19 -0
  277. package/src/testing/steps/util/require.step.ts +16 -0
  278. package/src/testing/steps/util/sleep.step.ts +15 -0
  279. package/tsconfig.json +35 -25
  280. package/tsconfig.tests.json +14 -0
  281. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -26,7 +26,6 @@ export class ServiceController {
26
26
  private readonly mqMessageService: MqMessageService,
27
27
  private readonly errorMapper: ErrorMapperService,
28
28
  private readonly ingestMetadataService: IngestMetadataService,
29
-
30
29
  ) { }
31
30
 
32
31
  @Public()
@@ -35,64 +34,64 @@ export class ServiceController {
35
34
  return { pong: 'v1.0.2' };
36
35
  }
37
36
 
38
- @ApiBearerAuth("jwt")
39
- @Get('mcp/ping')
40
- async mcpPingPong(@ActiveUser() activeUser: ActiveUserData) {
41
- // TODO: do a MCP client invocation, wait for response and return.
42
- // If failure then decide shape to return.
43
-
44
- const threadId = `pingPongTxn-${activeUser.sub}`;
45
- const dto ={prompt:"Can you do 1 + 1", moduleName:"solidCoreModule"}
46
- const { queueMessageId, aiInteractionId } = await this.aiInteractionService.triggerMcpClientJob(
47
- dto,
48
- activeUser.sub,
49
- true,
50
- threadId
51
- );
52
-
53
- this.logger.debug(`mcp ping pong job triggered: queueMessageId=${queueMessageId}, aiInteractionId=${aiInteractionId}`);
54
-
55
- // Wait up to 2 minutes, start at 500ms poll, back off to max 2s, throw if failed:
56
- const result = await this.mqMessageService.waitForTerminalStatus(queueMessageId, {
57
- timeoutMs: 2 * 60 * 1000,
58
- intervalMs: 500,
59
- maxIntervalMs: 2000,
60
- throwOnFailure: false,
61
- });
62
-
63
- this.logger.debug(`mcp ping pong job finished with stage=${result.stage}`)
64
-
65
- this.logger.debug(`mcp ping pong trying to find genai (child) interaction for aiInteraction for id=${aiInteractionId}`)
66
-
67
- // @ts-ignore
68
- const genAiInteractions = await this.aiInteractionService.find({
69
- filters: {
70
- parentInteraction: {
71
- id: {
72
- $eq: aiInteractionId
73
- }
74
- }
75
- }
76
- });
77
-
78
- const genAiInteraction = genAiInteractions['records'][0];
79
- this.logger.debug(genAiInteraction.message);
80
-
81
- this.logger.debug(`identified gen-ai interaction with id=${genAiInteraction.id}`);
82
- this.logger.debug(`proceeding with applying the gen-ai interaction`)
83
-
84
- return {
85
- mcpPong: 'v1.0.2',
86
- genAiInteraction: {
87
- status: genAiInteraction.status,
88
- errorCode: genAiInteraction.status === 'failed' ? this.errorMapper.mapMessage(genAiInteraction.errorMessage, genAiInteraction.metadata) : '',
89
- errorMessage: genAiInteraction.errorMessage,
90
- }
91
- };
92
- }
37
+ // @ApiBearerAuth("jwt")
38
+ // @Get('mcp/ping')
39
+ // async mcpPingPong(@ActiveUser() activeUser: ActiveUserData) {
40
+ // // TODO: do a MCP client invocation, wait for response and return.
41
+ // // If failure then decide shape to return.
42
+
43
+ // const threadId = `pingPongTxn-${activeUser.sub}`;
44
+ // const dto = { prompt: "Can you do 1 + 1", moduleName: "solidCoreModule" }
45
+ // const { queueMessageId, aiInteractionId } = await this.aiInteractionService.triggerMcpClientJob(
46
+ // dto,
47
+ // activeUser.sub,
48
+ // true,
49
+ // threadId
50
+ // );
51
+
52
+ // this.logger.debug(`mcp ping pong job triggered: queueMessageId=${queueMessageId}, aiInteractionId=${aiInteractionId}`);
53
+
54
+ // // Wait up to 2 minutes, start at 500ms poll, back off to max 2s, throw if failed:
55
+ // const result = await this.mqMessageService.waitForTerminalStatus(queueMessageId, {
56
+ // timeoutMs: 2 * 60 * 1000,
57
+ // intervalMs: 500,
58
+ // maxIntervalMs: 2000,
59
+ // throwOnFailure: false,
60
+ // });
61
+
62
+ // this.logger.debug(`mcp ping pong job finished with stage=${result.stage}`)
63
+
64
+ // this.logger.debug(`mcp ping pong trying to find genai (child) interaction for aiInteraction for id=${aiInteractionId}`)
65
+
66
+ // // @ts-ignore
67
+ // const genAiInteractions = await this.aiInteractionService.find({
68
+ // filters: {
69
+ // parentInteraction: {
70
+ // id: {
71
+ // $eq: aiInteractionId
72
+ // }
73
+ // }
74
+ // }
75
+ // });
76
+
77
+ // const genAiInteraction = genAiInteractions['records'][0];
78
+ // this.logger.debug(genAiInteraction.message);
79
+
80
+ // this.logger.debug(`identified gen-ai interaction with id=${genAiInteraction.id}`);
81
+ // this.logger.debug(`proceeding with applying the gen-ai interaction`)
82
+
83
+ // return {
84
+ // mcpPong: 'v1.0.2',
85
+ // genAiInteraction: {
86
+ // status: genAiInteraction.status,
87
+ // errorCode: genAiInteraction.status === 'failed' ? this.errorMapper.mapMessage(genAiInteraction.errorMessage, genAiInteraction.metadata) : '',
88
+ // errorMessage: genAiInteraction.errorMessage,
89
+ // }
90
+ // };
91
+ // }
93
92
 
94
- @Public()
95
93
  // @SkipThrottle({ short: false, login: true, burst: true, sustained: true }) //Enable the short throttle only
94
+ @ApiBearerAuth("jwt")
96
95
  @Post('seed')
97
96
  async seedData(@Body() seedData: any) {
98
97
  const seeder = this.solidRegistry
@@ -111,7 +110,7 @@ export class ServiceController {
111
110
 
112
111
  @ApiBearerAuth("jwt")
113
112
  @Post('code-generation/post-process')
114
- async postProcessCodeGeneration(@Body() config : PostProcessCodeGenConfig) {
113
+ async postProcessCodeGeneration(@Body() config: PostProcessCodeGenConfig) {
115
114
  // Set defaults if not provided
116
115
  config.runModuleMetadataSeeder = config.runModuleMetadataSeeder ?? true;
117
116
  config.runSolidIngestion = config.runSolidIngestion ?? true;
@@ -132,7 +131,7 @@ export class ServiceController {
132
131
  } else {
133
132
  this.logger.debug(`Skipping the Module Metadata Seeder Service as part of post-process code generation`);
134
133
  }
135
-
134
+
136
135
  // Run the Solid ingestion command
137
136
  if (config.runSolidIngestion) {
138
137
  this.logger.debug(`Running the Solid ingestion command as part of post-process code generation`);
@@ -28,12 +28,10 @@ export class BasicFilterDto extends PaginationQueryDto {
28
28
  @ApiProperty({ description: "aggregates" })
29
29
  readonly aggregates?: string[];
30
30
 
31
-
32
31
  @IsOptional()
33
32
  @ApiProperty({ description: "populate" })
34
33
  readonly populate?: string[];
35
34
 
36
-
37
35
  @IsOptional()
38
36
  @ApiProperty({ description: "populateMedia" })
39
37
  readonly populateMedia?: string[];
@@ -5,6 +5,7 @@ import { Type } from 'class-transformer';
5
5
  import { UpdateRoleMetadataDto } from 'src/dtos/update-role-metadata.dto';
6
6
  import { UpdateUserViewMetadataDto } from 'src/dtos/update-user-view-metadata.dto';
7
7
 
8
+ export const DEFAULT_SA_PASSWORD = 'Admin@3214$';
8
9
  export class CreateUserDto {
9
10
  @IsOptional()
10
11
  @IsString()
package/src/index.ts CHANGED
@@ -4,6 +4,8 @@ export * from './commands/refresh-module.command'
4
4
  export * from './commands/remove-fields.command'
5
5
  export * from './commands/seed.command'
6
6
  export * from './commands/test-data.command'
7
+ export * from './commands/run-tests.command'
8
+ export * from './commands/test.command'
7
9
 
8
10
  export * from './config/cache.options'
9
11
 
@@ -179,6 +181,7 @@ export * from './helpers/security.helper'
179
181
  export * from './helpers/model-metadata-helper.service'
180
182
  export * from './helpers/image-encoding.helper'
181
183
  export * from './helpers/solid-microservice-adapter.service'
184
+ export * from './helpers/typeorm-db-helper';
182
185
 
183
186
  export * from './services/crud.service'
184
187
  export * from './interceptors/logging.interceptor'
@@ -31,7 +31,7 @@ import { ViewMetadataService } from '../services/view-metadata.service';
31
31
  import solidCoreMetadata from './seed-data/solid-core-metadata.json';
32
32
  import { SystemFieldsSeederService } from './system-fields-seeder.service';
33
33
  // import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto';
34
- import { ActionMetadata, MENU_ROLE_JOIN_TABLE_NAME, MENU_ROLE_JOIN_TABLE_NAME_MENU_COL, MENU_ROLE_JOIN_TABLE_NAME_ROLE_COL, MenuItemMetadata, ModuleMetadata, RoleMetadata, SignUpDto } from 'src';
34
+ import { ActionMetadata, DEFAULT_SA_PASSWORD, MENU_ROLE_JOIN_TABLE_NAME, MENU_ROLE_JOIN_TABLE_NAME_MENU_COL, MENU_ROLE_JOIN_TABLE_NAME_ROLE_COL, MenuItemMetadata, ModuleMetadata, RoleMetadata, SignUpDto } from 'src';
35
35
  import { ADMIN_ROLE_NAME } from 'src/dtos/create-role-metadata.dto';
36
36
  import { CreateSavedFiltersDto } from 'src/dtos/create-saved-filters.dto';
37
37
  import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto';
@@ -768,7 +768,7 @@ export class ModuleMetadataSeederService {
768
768
  }
769
769
 
770
770
  // OK
771
- private async handleSeedUsers(users) {
771
+ private async handleSeedUsers(users: SignUpDto[]) {
772
772
  if (!users) {
773
773
  return;
774
774
  }
@@ -777,33 +777,12 @@ export class ModuleMetadataSeederService {
777
777
  const user: SignUpDto = users[l];
778
778
  let exisitingUser = await this.userService.findOneByUsername(user.username);
779
779
  if (!exisitingUser) {
780
- let generatedAdminPassword: string | null = null;
781
780
  if (user.username === 'sa') {
782
- generatedAdminPassword = uuidv4();
783
- user.password = generatedAdminPassword;
781
+ user.password = DEFAULT_SA_PASSWORD;
784
782
  }
785
783
 
786
784
  exisitingUser = await this.authenticationService.signUp(user);
787
785
  this.logger.log(`Newly created user ${user.username}`);
788
-
789
- // Surface the generated SA password clearly to the operator.
790
- if (generatedAdminPassword) {
791
- const banner = [
792
- '',
793
- '============================================================',
794
- ' SYSTEM ADMIN USER CREATED',
795
- '------------------------------------------------------------',
796
- ' Username : sa',
797
- ` Password : ${generatedAdminPassword}`,
798
- '',
799
- ' Copy and store this password securely now.',
800
- ' It is shown only once during seeding.',
801
- '============================================================',
802
- ''
803
- ].join('\n');
804
- // Use console.log to ensure visibility even if logger formatting changes.
805
- console.log(banner);
806
- }
807
786
  }
808
787
  //FIXME: Create the user roles assignment logic here.
809
788
  // now add Roles to user.
@@ -185,8 +185,10 @@ export class ModuleTestDataService {
185
185
  throw new Error('Module metadata missing from test data payload.');
186
186
  }
187
187
 
188
- const testData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata.testData ?? [];
189
- if (testData.length === 0) {
188
+ // console.log(JSON.stringify(moduleMetadata, null, 2));
189
+
190
+ const testingData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata?.testing?.data ?? [];
191
+ if (testingData.length === 0) {
190
192
  this.logger.debug(`No test data found for ${moduleMetadata.name}`);
191
193
  return;
192
194
  }
@@ -195,7 +197,7 @@ export class ModuleTestDataService {
195
197
  (moduleMetadata.models ?? []).map((m) => [m.singularName, m]),
196
198
  );
197
199
 
198
- for (const entry of testData) {
200
+ for (const entry of testingData) {
199
201
  const modelUserKey = entry.modelUserKey;
200
202
  const modelDef = modelsByName.get(modelUserKey);
201
203
  if (!modelDef) {
@@ -18,9 +18,12 @@ import { ChatterMessageDetails } from '../entities/chatter-message-details.entit
18
18
  import { ChatterMessage } from '../entities/chatter-message.entity';
19
19
  import { getMediaStorageProvider } from './mediaStorageProviders';
20
20
  import { RequestContextService } from './request-context.service';
21
- import { take } from 'rxjs';
21
+ import { Logger } from '@nestjs/common';
22
+
22
23
  @Injectable()
23
24
  export class ChatterMessageService extends CRUDService<ChatterMessage> {
25
+ private readonly _logger = new Logger(ChatterMessageService.name);
26
+
24
27
  constructor(
25
28
  @InjectEntityManager()
26
29
  readonly entityManager: EntityManager,
@@ -502,16 +505,23 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
502
505
  return populatedEntity;
503
506
  }
504
507
 
508
+ private logHeapUsed(label: string) {
509
+ const mb = () => Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
510
+ this._logger.log(`heapUsedMB(${label}): ${mb()}`);
511
+ }
512
+
505
513
  // [2026-02-05T23:31:21.025Z] INFO: [200 OK]
506
514
  // GET /api/chatter-message/getChatterMessages/216/mswipeBoomboxBulkUpload?populateMedia[0]=messageAttachments&populate[0]=user&populate[1]=chatterMessageDetails&limit=25 22747ms
507
515
  async getChatterMessages(entityId: number, entityName: string, query: any) {
508
516
  const { limit = 25, offset = 0, populate = [], populateMedia = [], filters } = query;
517
+ this.logHeapUsed('getChatterMessages-start');
509
518
 
510
519
  const model = await this.modelMetadataRepo.findOne({
511
520
  where: {
512
521
  singularName: entityName
513
522
  },
514
523
  });
524
+ this.logHeapUsed('getChatterMessages-modelLoaded');
515
525
  const oneToManyFields = await this.fieldMetadataRepo.find({
516
526
  where: {
517
527
  model: { id: model.id },
@@ -519,11 +529,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
519
529
  relationType: 'one-to-many'
520
530
  }
521
531
  });
532
+ this.logHeapUsed('getChatterMessages-oneToManyFieldsLoaded');
522
533
 
523
534
  const relatedEntitiesMap = new Map<string, number[]>();
524
535
 
525
536
  for (const field of oneToManyFields) {
526
537
  if (field.enableAuditTracking === false) {
538
+ this._logger.log(`Skipping field ${field.name} for chatter message retrieval because audit tracking is disabled`);
527
539
  continue
528
540
  }
529
541
  const coModelName = field.relationCoModelSingularName;
@@ -552,8 +564,10 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
552
564
  relatedEntitiesMap.set(field.name, relatedIds);
553
565
  }
554
566
  }
567
+ this.logHeapUsed('getChatterMessages-relatedEntitiesLoaded');
555
568
 
556
569
  const qb = await this.repo.createSecurityRuleAwareQueryBuilder('entity');
570
+ this.logHeapUsed('getChatterMessages-queryBuilderReady');
557
571
 
558
572
  const orConditions: string[] = [];
559
573
  const parameters: any = {};
@@ -602,10 +616,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
602
616
  qb.skip(offset).take(limit);
603
617
 
604
618
  const [entities, count] = await qb.getManyAndCount();
619
+ this.logHeapUsed('getChatterMessages-entitiesLoaded');
605
620
 
606
621
  if (populateMedia && populateMedia.length > 0) {
607
622
  const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
623
+ this.logHeapUsed('getChatterMessages-beforePopulateMedia');
608
624
  await this['handlePopulateMedia'](normalizedPopulateMedia, entities);
625
+ this.logHeapUsed('getChatterMessages-afterPopulateMedia');
609
626
  }
610
627
 
611
628
  const currentPage = Math.floor(offset / limit) + 1;
@@ -67,6 +67,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
67
67
  protected get discoveryService(): DiscoveryService {
68
68
  return this._discoveryService ??= this.moduleRef.get(DiscoveryService, { strict: false });
69
69
  }
70
+
70
71
  protected get settingService(): SettingService {
71
72
  return this._settingService ??= this.moduleRef.get(SettingService, { strict: false });
72
73
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Convert a string into a lower-case slug separated by a join character.
3
+ *
4
+ * Logic:
5
+ * - Keep only ASCII letters and digits.
6
+ * - Convert A-Z to a-z.
7
+ * - Replace runs of non-alphanumeric characters with a single join character.
8
+ * - Trim leading/trailing join characters.
9
+ *
10
+ * Examples (joinChar "_"):
11
+ * - "Venue App" -> "venue_app"
12
+ * - "My-App@2025" -> "my_app_2025"
13
+ * - " CORE__API!! " -> "core_api"
14
+ *
15
+ * Examples (joinChar "-"):
16
+ * - "Venue App" -> "venue-app"
17
+ */
18
+ export function toSlug(value?: string | null, joinChar: string = '-'): string {
19
+ if (!value) {
20
+ return '';
21
+ }
22
+
23
+ const slugChars: string[] = [];
24
+ let lastJoin = true;
25
+
26
+ for (let i = 0; i < value.length; i += 1) {
27
+ const code = value.charCodeAt(i);
28
+
29
+ // ASCII uppercase -> lowercase
30
+ if (code >= 65 && code <= 90) {
31
+ slugChars.push(String.fromCharCode(code + 32));
32
+ lastJoin = false;
33
+ continue;
34
+ }
35
+
36
+ // ASCII lowercase letters or digits are kept as-is
37
+ if ((code >= 97 && code <= 122) || (code >= 48 && code <= 57)) {
38
+ slugChars.push(value[i]);
39
+ lastJoin = false;
40
+ continue;
41
+ }
42
+
43
+ // Any other char becomes a single join character (collapse runs)
44
+ if (!lastJoin && slugChars.length > 0) {
45
+ slugChars.push(joinChar);
46
+ lastJoin = true;
47
+ }
48
+ }
49
+
50
+ if (slugChars.length && slugChars[slugChars.length - 1] === joinChar) {
51
+ slugChars.pop();
52
+ }
53
+
54
+ return slugChars.join('');
55
+ }
56
+
57
+ /**
58
+ * Build a namespaced queue name by prefixing the queue name with the
59
+ * slugged app name, the slugged env, and underscores.
60
+ *
61
+ * Examples:
62
+ * - appName "Venue App", env "Prod", queue "orders" -> "venue_app_prod_orders"
63
+ * - appName "core-api", env "staging", queue "sync" -> "core_api_staging_sync"
64
+ * - appName "" or undefined, env "" or undefined, queue "jobs" -> "_dev_jobs"
65
+ */
66
+ export function buildNamespacedQueueName(
67
+ queueName: string,
68
+ appName: string | undefined | null = process.env.SOLID_APP_NAME,
69
+ env: string | undefined | null = process.env.ENV,
70
+ ): string {
71
+ const appNameSlug = toSlug(appName, '_');
72
+ const envValue = env && env.length > 0 ? env : (process.env.ENV && process.env.ENV.length > 0 ? process.env.ENV : 'dev');
73
+ const envSlug = toSlug(envValue, '_');
74
+ return `${appNameSlug}_${envSlug}_${queueName}`;
75
+ }
@@ -4,6 +4,7 @@ import { QueuesModuleOptions } from "../../interfaces";
4
4
  import { QueueMessage, QueuePublisher } from '../../interfaces/mq';
5
5
  import { MqMessageQueueService } from '../mq-message-queue.service';
6
6
  import { MqMessageService } from '../mq-message.service';
7
+ import { buildNamespacedQueueName } from './common';
7
8
 
8
9
  export abstract class DatabasePublisher<T> implements QueuePublisher<T> {
9
10
  private readonly logger = new Logger(DatabasePublisher.name);
@@ -38,6 +39,8 @@ export abstract class DatabasePublisher<T> implements QueuePublisher<T> {
38
39
  const options = this.options();
39
40
 
40
41
  const queueName = options.queueName;
42
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
43
+
41
44
  if (!message.retryCount) message.retryCount = 0;
42
45
  if (!message.retryInterval) message.retryInterval = 1000;
43
46
 
@@ -45,7 +48,7 @@ export abstract class DatabasePublisher<T> implements QueuePublisher<T> {
45
48
  message.messageId = uuidv4();
46
49
 
47
50
  // Save the message to the DB so that we can then change its status in the subscriber...
48
- await this.persistToDatabase(queueName, message);
51
+ await this.persistToDatabase(namespacedQueueName, message);
49
52
 
50
53
  // return the newly created message id.
51
54
  return message.messageId;
@@ -4,7 +4,7 @@ import { QueueMessage, QueueSubscriber } from '../../interfaces/mq';
4
4
  import { MqMessageQueueService } from '../mq-message-queue.service';
5
5
  import { MqMessageService } from '../mq-message.service';
6
6
  import { PollerService } from '../poller.service';
7
-
7
+ import { buildNamespacedQueueName } from './common';
8
8
 
9
9
  export abstract class DatabaseSubscriber<T> implements OnModuleInit, QueueSubscriber<T> {
10
10
  private readonly logger = new Logger(DatabaseSubscriber.name);
@@ -97,7 +97,8 @@ export abstract class DatabaseSubscriber<T> implements OnModuleInit, QueueSubscr
97
97
  }
98
98
  }
99
99
 
100
- this.poller.start(queueName, (q) => this.processNext(q), {
100
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
101
+ this.poller.start(namespacedQueueName, (q) => this.processNext(q), {
101
102
  baseDelayMs: 1000,
102
103
  maxDelayMs: 30_000,
103
104
  timeoutPerIterationMs: 5 * 60_000,
@@ -111,7 +112,8 @@ export abstract class DatabaseSubscriber<T> implements OnModuleInit, QueueSubscr
111
112
  onModuleDestroy() {
112
113
  const options = this.options();
113
114
  const queueName = options.queueName;
114
- this.poller.stop(queueName);
115
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
116
+ this.poller.stop(namespacedQueueName);
115
117
  }
116
118
 
117
119
  /**
@@ -5,6 +5,7 @@ import { QueuesModuleOptions } from "../../interfaces";
5
5
  import { QueueMessage, QueuePublisher } from '../../interfaces/mq';
6
6
  import { MqMessageQueueService } from '../mq-message-queue.service';
7
7
  import { MqMessageService } from '../mq-message.service';
8
+ import { buildNamespacedQueueName } from './common';
8
9
 
9
10
  export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePublisher<T> {
10
11
  private readonly logger = new Logger(RabbitMqPublisher.name);
@@ -70,13 +71,21 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
70
71
 
71
72
  const channel = await conn.createChannel();
72
73
 
74
+ channel.on('return', (msg) => {
75
+ const content = msg.content?.toString?.() ?? '';
76
+ this.logger.warn(
77
+ `RabbitMqPublisher message returned from exchange ${msg.fields.exchange} with routingKey ${msg.fields.routingKey}: ${content}`,
78
+ );
79
+ });
80
+
73
81
  const options = this.options();
74
82
  const queueName = options.queueName;
75
- const exchangeName = `${queueName}.exchange`;
76
- const routingKey = `${queueName}.routing-key`;
83
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
84
+ const exchangeName = `${namespacedQueueName}.exchange`;
85
+ const routingKey = `${namespacedQueueName}.routing-key`;
77
86
 
78
87
  await channel.assertExchange(exchangeName, 'direct', {});
79
- const queue = await channel.assertQueue(queueName, {});
88
+ const queue = await channel.assertQueue(namespacedQueueName, {});
80
89
  await channel.bindQueue(queue.queue, exchangeName, routingKey);
81
90
 
82
91
  this.connection = conn;
@@ -127,7 +136,6 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
127
136
  }
128
137
  }
129
138
 
130
-
131
139
  async publish(message: QueueMessage<T>): Promise<string> {
132
140
  if (!this.url) {
133
141
  this.logger.error('RabbitMqPublisher url is not defined in the environment variables');
@@ -148,8 +156,10 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
148
156
  const options = this.options();
149
157
 
150
158
  const queueName = options.queueName;
151
- const exchangeName = `${queueName}.exchange`;
152
- const routingKey = `${queueName}.routing-key`;
159
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
160
+
161
+ const exchangeName = `${namespacedQueueName}.exchange`;
162
+ const routingKey = `${namespacedQueueName}.routing-key`;
153
163
 
154
164
  // Set default values for retry.
155
165
  // by default there are no retries.
@@ -160,7 +170,7 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
160
170
  message.messageId = uuidv4();
161
171
 
162
172
  // Save the message to the DB so that we can then change its status in the subscriber...
163
- await this.persistToDatabase(queueName, message);
173
+ await this.persistToDatabase(namespacedQueueName, message);
164
174
 
165
175
  // wait for the channel to confirm
166
176
  try {
@@ -4,6 +4,7 @@ import { QueuesModuleOptions } from "../../interfaces";
4
4
  import { QueueMessage, QueueSubscriber } from '../../interfaces/mq';
5
5
  import { MqMessageQueueService } from '../mq-message-queue.service';
6
6
  import { MqMessageService } from '../mq-message.service';
7
+ import { buildNamespacedQueueName } from './common';
7
8
 
8
9
 
9
10
  export abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscriber<T> { // TODO This can be made a generic type for better type visibility
@@ -80,19 +81,21 @@ export abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscr
80
81
  }
81
82
  }
82
83
 
84
+ const namespacedQueueName = buildNamespacedQueueName(queueName);
83
85
  try {
84
- await this.connectAndConsume(queueName);
86
+ await this.connectAndConsume(namespacedQueueName);
85
87
  } catch (err) {
86
- this.logger.error(`Failed to connect to RabbitMQ for queue ${queueName}: ${(err as Error).message}`, (err as Error).stack);
87
- this.triggerReconnect(queueName, 'initial connection failure');
88
+ this.logger.error(`Failed to connect to RabbitMQ for queue ${namespacedQueueName}: ${(err as Error).message}`, (err as Error).stack);
89
+ this.triggerReconnect(namespacedQueueName, 'initial connection failure');
88
90
  }
89
91
 
90
- this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${this.url}`);
92
+ this.logger.log(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(options)} and url: ${this.url}`);
91
93
  }
92
94
  }
93
95
 
94
96
  private async connectAndConsume(queueName: string): Promise<void> {
95
97
  await this.cleanup();
98
+ this.logger.log(`RabbitMqSubscriber in connectAndConsume for queue: ${queueName} and url: ${this.url}`);
96
99
 
97
100
  let connection: amqp.Connection;
98
101
  try {
@@ -159,11 +162,12 @@ export abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscr
159
162
  return;
160
163
  }
161
164
 
162
- const messageContentString = rawMessage.content.toString();
163
165
  let message: QueueMessage<T> = null;
164
166
 
165
167
  try {
168
+ const messageContentString = rawMessage.content.toString();
166
169
  message = JSON.parse(messageContentString) as QueueMessage<T>;
170
+ this.logger.debug(`rabbitmq subscriber received message with id: ${message.messageId} for queue ${queueName}`);
167
171
  } catch (error) {
168
172
  this.logger.error(`Invalid JSON message on queue ${queueName}: ${(error as Error).message}`);
169
173
  await this.publishToFailedQueue(queueName, rawMessage.content, channel, error);
@@ -58,6 +58,8 @@ import { HttpModule } from '@nestjs/axios';
58
58
  import { JwtModule } from '@nestjs/jwt';
59
59
  import { SeedCommand } from './commands/seed.command';
60
60
  import { TestDataCommand } from './commands/test-data.command';
61
+ import { TestRunCommand } from './commands/run-tests.command';
62
+ import { TestCommand } from './commands/test.command';
61
63
  import { AuthenticationController } from './controllers/authentication.controller';
62
64
  import { EmailTemplateController } from './controllers/email-template.controller';
63
65
  import { GoogleAuthenticationController } from './controllers/google-authentication.controller';
@@ -506,7 +508,9 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
506
508
  TextractService,
507
509
  SolidRegistry,
508
510
  SeedCommand,
511
+ TestCommand,
509
512
  TestDataCommand,
513
+ TestRunCommand,
510
514
  McpCommand,
511
515
  IngestCommand,
512
516
  IngestMetadataService,