@friggframework/core 2.0.0--canary.549.a579cca.0 → 2.0.0--canary.549.70ef06a.0

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 (305) hide show
  1. package/assertions/jest.config.ts +7 -0
  2. package/database/jest.config.ts +7 -0
  3. package/database/models/WorkflowExecutionModel.ts +315 -0
  4. package/database/models/WorkflowModel.ts +129 -0
  5. package/jest-global-setup-noop.ts +3 -0
  6. package/jest-global-teardown-noop.ts +3 -0
  7. package/jest-resolver.ts +36 -0
  8. package/jest-setup.ts +2 -0
  9. package/jest-teardown.ts +2 -0
  10. package/jest.config.ts +20 -0
  11. package/package.json +8 -5
  12. package/src/application/commands/integration-commands.test.ts +158 -0
  13. package/src/application/commands/integration-commands.ts +20 -35
  14. package/src/core/Worker.test.ts +158 -0
  15. package/src/database/adapters/lambda-invoker.test.ts +104 -0
  16. package/src/database/encryption/encryption-schema-registry.test.ts +397 -0
  17. package/src/database/encryption/field-encryption-service.test.ts +511 -0
  18. package/src/database/encryption/mongo-decryption-fix-verification.test.ts +337 -0
  19. package/src/database/encryption/postgres-decryption-fix-verification.test.ts +335 -0
  20. package/src/database/encryption/postgres-relation-decryption.test.ts +205 -0
  21. package/src/database/encryption/prisma-encryption-extension.test.ts +433 -0
  22. package/src/database/prisma.test.ts +65 -0
  23. package/src/database/repositories/health-check-repository-mongodb.test.ts +178 -0
  24. package/src/database/repositories/health-check-repository-postgres.test.ts +94 -0
  25. package/src/database/repositories/migration-status-repository-s3.test.ts +150 -0
  26. package/src/database/use-cases/check-database-health-use-case.test.ts +131 -0
  27. package/src/database/use-cases/check-database-state-use-case.test.ts +131 -0
  28. package/src/database/use-cases/check-encryption-health-use-case.test.ts +183 -0
  29. package/src/database/use-cases/get-database-state-via-worker-use-case.test.ts +126 -0
  30. package/src/database/use-cases/get-migration-status-use-case.test.ts +160 -0
  31. package/src/database/use-cases/run-database-migration-use-case.test.ts +350 -0
  32. package/src/database/use-cases/trigger-database-migration-use-case.test.ts +256 -0
  33. package/src/database/utils/mongodb-collection-utils.test.ts +133 -0
  34. package/src/database/utils/mongodb-schema-init.test.ts +152 -0
  35. package/src/database/utils/prisma-runner.test.ts +513 -0
  36. package/src/database/utils/prisma-schema-parser.test.ts +283 -0
  37. package/src/declarations.d.ts +7 -0
  38. package/src/encrypt/Cryptor.test.ts +137 -0
  39. package/src/errors/base-error.test.ts +32 -0
  40. package/src/errors/fetch-error.test.ts +105 -0
  41. package/src/errors/halt-error.test.ts +11 -0
  42. package/src/errors/validation-errors.test.ts +122 -0
  43. package/src/handlers/auth-flow.integration.test.ts +149 -0
  44. package/src/handlers/integration-event-dispatcher.test.ts +211 -0
  45. package/src/handlers/routers/db-migration.test.ts +69 -0
  46. package/src/handlers/routers/health.test.ts +251 -0
  47. package/src/handlers/routers/health.ts +9 -12
  48. package/src/handlers/routers/integration-webhook-routers.test.ts +116 -0
  49. package/src/handlers/use-cases/check-integrations-health-use-case.test.ts +124 -0
  50. package/src/handlers/webhook-flow.integration.test.ts +318 -0
  51. package/src/handlers/workers/db-migration.test.ts +168 -0
  52. package/src/handlers/workers/db-migration.ts +11 -13
  53. package/src/handlers/workers/integration-defined-workers.test.ts +254 -0
  54. package/src/integrations/integration-base.module-keys.test.ts +204 -0
  55. package/{integrations/tests/doubles/config-capturing-integration.js → src/integrations/tests/doubles/config-capturing-integration.ts} +13 -13
  56. package/{integrations/tests/doubles/dummy-integration-class.js → src/integrations/tests/doubles/dummy-integration-class.ts} +21 -17
  57. package/{integrations/tests/doubles/test-integration-repository.js → src/integrations/tests/doubles/test-integration-repository.ts} +14 -13
  58. package/src/integrations/tests/integration-router-multi-auth.test.ts +531 -0
  59. package/src/integrations/tests/use-cases/create-integration.test.ts +131 -0
  60. package/src/integrations/tests/use-cases/delete-integration-for-user.test.ts +150 -0
  61. package/src/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.ts +92 -0
  62. package/src/integrations/tests/use-cases/get-integration-for-user.test.ts +150 -0
  63. package/src/integrations/tests/use-cases/get-integration-instance.test.ts +176 -0
  64. package/src/integrations/tests/use-cases/get-integrations-for-user.test.ts +176 -0
  65. package/src/integrations/tests/use-cases/get-possible-integrations.test.ts +188 -0
  66. package/src/integrations/tests/use-cases/update-integration-messages.test.ts +142 -0
  67. package/src/integrations/tests/use-cases/update-integration-status.test.ts +103 -0
  68. package/src/integrations/tests/use-cases/update-integration.test.ts +208 -0
  69. package/src/integrations/use-cases/create-process.test.ts +172 -0
  70. package/src/integrations/use-cases/get-process.test.ts +181 -0
  71. package/src/integrations/use-cases/load-integration-context-full.test.ts +316 -0
  72. package/src/integrations/use-cases/load-integration-context.test.ts +115 -0
  73. package/src/integrations/use-cases/update-process-metrics.test.ts +278 -0
  74. package/src/integrations/use-cases/update-process-state.test.ts +249 -0
  75. package/src/lambda/TimeoutCatcher.test.ts +69 -0
  76. package/src/logs/logger.test.ts +76 -0
  77. package/src/modules/module-hydration.test.ts +203 -0
  78. package/src/modules/module.ts +1 -1
  79. package/src/modules/requester/oauth-2.test.ts +425 -0
  80. package/src/modules/requester/requester.test.ts +28 -0
  81. package/{modules/test/mock-api/api.js → src/modules/test/mock-api/api.ts} +6 -8
  82. package/{modules/test/mock-api/definition.js → src/modules/test/mock-api/definition.ts} +13 -14
  83. package/{modules/test/mock-api/mocks/hubspot.js → src/modules/test/mock-api/mocks/hubspot.ts} +6 -8
  84. package/{modules/tests/doubles/test-module-factory.js → src/modules/tests/doubles/test-module-factory.ts} +2 -5
  85. package/{modules/tests/doubles/test-module-repository.js → src/modules/tests/doubles/test-module-repository.ts} +7 -7
  86. package/src/modules/tests/module-on-token-update.test.ts +125 -0
  87. package/src/queues/queuer-util.test.ts +131 -0
  88. package/{user/tests/doubles/test-user-repository.js → src/user/tests/doubles/test-user-repository.ts} +17 -15
  89. package/src/user/tests/use-cases/create-individual-user.test.ts +24 -0
  90. package/src/user/tests/use-cases/create-organization-user.test.ts +28 -0
  91. package/src/user/tests/use-cases/create-token-for-user-id.test.ts +18 -0
  92. package/src/user/tests/use-cases/get-user-from-adopter-jwt.test.ts +113 -0
  93. package/src/user/tests/use-cases/get-user-from-bearer-token.test.ts +64 -0
  94. package/src/user/tests/use-cases/get-user-from-x-frigg-headers.test.ts +440 -0
  95. package/src/user/tests/use-cases/login-user.test.ts +220 -0
  96. package/src/user/use-cases/authenticate-with-shared-secret.test.ts +127 -0
  97. package/src/websocket/repositories/websocket-connection-repository.test.ts +220 -0
  98. package/tsconfig.test.json +10 -0
  99. package/workflows/frigg-workflow.ts +322 -0
  100. package/workflows/index.ts +205 -0
  101. package/workflows/steps/fan-out-step.ts +275 -0
  102. package/workflows/steps/function-step.ts +174 -0
  103. package/workflows/steps/index.ts +30 -0
  104. package/workflows/steps/workflow-step.ts +115 -0
  105. package/workflows/use-cases/create-workflow.ts +332 -0
  106. package/workflows/use-cases/execute-workflow-step.ts +465 -0
  107. package/workflows/use-cases/execute-workflow.ts +403 -0
  108. package/workflows/workflow-execution-repository.ts +415 -0
  109. package/workflows/workflow-execution.ts +209 -0
  110. package/workflows/workflow-queue-service.ts +379 -0
  111. package/workflows/workflow-repository.ts +295 -0
  112. package/workflows/workflow.ts +117 -0
  113. package/application/commands/credential-commands.js +0 -245
  114. package/application/commands/entity-commands.js +0 -336
  115. package/application/commands/integration-commands.js +0 -210
  116. package/application/commands/scheduler-commands.js +0 -263
  117. package/application/commands/user-commands.js +0 -283
  118. package/application/index.js +0 -73
  119. package/assertions/get.js +0 -139
  120. package/assertions/index.js +0 -16
  121. package/assertions/jest.config.js +0 -5
  122. package/associations/association.js +0 -3
  123. package/core/Delegate.js +0 -29
  124. package/core/Worker.js +0 -72
  125. package/core/create-handler.js +0 -75
  126. package/core/index.js +0 -7
  127. package/core/load-installed-modules.js +0 -28
  128. package/core/secrets-to-env.js +0 -61
  129. package/credential/repositories/credential-repository-documentdb.js +0 -304
  130. package/credential/repositories/credential-repository-factory.js +0 -54
  131. package/credential/repositories/credential-repository-interface.js +0 -98
  132. package/credential/repositories/credential-repository-mongo.js +0 -269
  133. package/credential/repositories/credential-repository-postgres.js +0 -287
  134. package/credential/repositories/credential-repository.js +0 -300
  135. package/credential/use-cases/get-credential-for-user.js +0 -25
  136. package/credential/use-cases/update-authentication-status.js +0 -15
  137. package/database/adapters/lambda-invoker.js +0 -97
  138. package/database/config.js +0 -154
  139. package/database/documentdb-encryption-service.js +0 -330
  140. package/database/documentdb-utils.js +0 -136
  141. package/database/encryption/encryption-schema-registry.js +0 -272
  142. package/database/encryption/field-encryption-service.js +0 -226
  143. package/database/encryption/logger.js +0 -79
  144. package/database/encryption/prisma-encryption-extension.js +0 -222
  145. package/database/index.js +0 -25
  146. package/database/jest.config.js +0 -5
  147. package/database/prisma.js +0 -182
  148. package/database/repositories/health-check-repository-documentdb.js +0 -138
  149. package/database/repositories/health-check-repository-factory.js +0 -48
  150. package/database/repositories/health-check-repository-interface.js +0 -82
  151. package/database/repositories/health-check-repository-mongodb.js +0 -89
  152. package/database/repositories/health-check-repository-postgres.js +0 -82
  153. package/database/repositories/migration-status-repository-s3.js +0 -137
  154. package/database/use-cases/check-database-health-use-case.js +0 -29
  155. package/database/use-cases/check-database-state-use-case.js +0 -81
  156. package/database/use-cases/check-encryption-health-use-case.js +0 -83
  157. package/database/use-cases/get-database-state-via-worker-use-case.js +0 -61
  158. package/database/use-cases/get-migration-status-use-case.js +0 -93
  159. package/database/use-cases/run-database-migration-use-case.js +0 -139
  160. package/database/use-cases/test-encryption-use-case.js +0 -253
  161. package/database/use-cases/trigger-database-migration-use-case.js +0 -157
  162. package/database/utils/mongodb-collection-utils.js +0 -94
  163. package/database/utils/mongodb-schema-init.js +0 -108
  164. package/database/utils/prisma-runner.js +0 -477
  165. package/database/utils/prisma-schema-parser.js +0 -182
  166. package/encrypt/Cryptor.js +0 -102
  167. package/encrypt/aes.js +0 -27
  168. package/encrypt/index.js +0 -3
  169. package/errors/base-error.js +0 -3
  170. package/errors/client-safe-error.js +0 -3
  171. package/errors/fetch-error.js +0 -3
  172. package/errors/halt-error.js +0 -3
  173. package/errors/index.js +0 -14
  174. package/errors/validation-errors.js +0 -3
  175. package/handlers/app-definition-loader.js +0 -38
  176. package/handlers/app-handler-helpers.js +0 -57
  177. package/handlers/backend-utils.js +0 -186
  178. package/handlers/database-migration-handler.js +0 -227
  179. package/handlers/integration-event-dispatcher.js +0 -54
  180. package/handlers/routers/auth.js +0 -15
  181. package/handlers/routers/db-migration.handler.js +0 -29
  182. package/handlers/routers/db-migration.js +0 -326
  183. package/handlers/routers/health.js +0 -516
  184. package/handlers/routers/integration-defined-routers.js +0 -45
  185. package/handlers/routers/integration-webhook-routers.js +0 -67
  186. package/handlers/routers/user.js +0 -63
  187. package/handlers/routers/websocket.js +0 -57
  188. package/handlers/use-cases/check-external-apis-health-use-case.js +0 -81
  189. package/handlers/use-cases/check-integrations-health-use-case.js +0 -44
  190. package/handlers/workers/db-migration.js +0 -352
  191. package/handlers/workers/integration-defined-workers.js +0 -27
  192. package/index.js +0 -176
  193. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +0 -184
  194. package/infrastructure/scheduler/index.js +0 -33
  195. package/infrastructure/scheduler/mock-scheduler-adapter.js +0 -143
  196. package/infrastructure/scheduler/scheduler-service-factory.js +0 -73
  197. package/infrastructure/scheduler/scheduler-service-interface.js +0 -47
  198. package/integrations/index.js +0 -21
  199. package/integrations/integration-base.js +0 -535
  200. package/integrations/integration-router.js +0 -666
  201. package/integrations/options.js +0 -53
  202. package/integrations/repositories/integration-mapping-repository-documentdb.js +0 -280
  203. package/integrations/repositories/integration-mapping-repository-factory.js +0 -57
  204. package/integrations/repositories/integration-mapping-repository-interface.js +0 -106
  205. package/integrations/repositories/integration-mapping-repository-mongo.js +0 -161
  206. package/integrations/repositories/integration-mapping-repository-postgres.js +0 -227
  207. package/integrations/repositories/integration-mapping-repository.js +0 -156
  208. package/integrations/repositories/integration-repository-documentdb.js +0 -210
  209. package/integrations/repositories/integration-repository-factory.js +0 -51
  210. package/integrations/repositories/integration-repository-interface.js +0 -127
  211. package/integrations/repositories/integration-repository-mongo.js +0 -303
  212. package/integrations/repositories/integration-repository-postgres.js +0 -352
  213. package/integrations/repositories/process-repository-documentdb.js +0 -243
  214. package/integrations/repositories/process-repository-factory.js +0 -53
  215. package/integrations/repositories/process-repository-interface.js +0 -90
  216. package/integrations/repositories/process-repository-mongo.js +0 -190
  217. package/integrations/repositories/process-repository-postgres.js +0 -217
  218. package/integrations/use-cases/create-integration.js +0 -83
  219. package/integrations/use-cases/create-process.js +0 -128
  220. package/integrations/use-cases/delete-integration-for-user.js +0 -101
  221. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +0 -72
  222. package/integrations/use-cases/get-integration-for-user.js +0 -78
  223. package/integrations/use-cases/get-integration-instance-by-definition.js +0 -67
  224. package/integrations/use-cases/get-integration-instance.js +0 -83
  225. package/integrations/use-cases/get-integrations-for-user.js +0 -88
  226. package/integrations/use-cases/get-possible-integrations.js +0 -27
  227. package/integrations/use-cases/get-process.js +0 -87
  228. package/integrations/use-cases/index.js +0 -19
  229. package/integrations/use-cases/load-integration-context.js +0 -71
  230. package/integrations/use-cases/update-integration-messages.js +0 -44
  231. package/integrations/use-cases/update-integration-status.js +0 -32
  232. package/integrations/use-cases/update-integration.js +0 -92
  233. package/integrations/use-cases/update-process-metrics.js +0 -201
  234. package/integrations/use-cases/update-process-state.js +0 -119
  235. package/integrations/utils/map-integration-dto.js +0 -38
  236. package/jest-global-setup-noop.js +0 -3
  237. package/jest-global-teardown-noop.js +0 -3
  238. package/jest-setup.js +0 -2
  239. package/jest-teardown.js +0 -2
  240. package/jest.config.js +0 -21
  241. package/lambda/TimeoutCatcher.js +0 -43
  242. package/lambda/index.js +0 -3
  243. package/logs/index.js +0 -7
  244. package/logs/logger.js +0 -65
  245. package/modules/ModuleConstants.js +0 -10
  246. package/modules/index.js +0 -15
  247. package/modules/module-factory.js +0 -56
  248. package/modules/module.js +0 -228
  249. package/modules/repositories/module-repository-documentdb.js +0 -335
  250. package/modules/repositories/module-repository-factory.js +0 -40
  251. package/modules/repositories/module-repository-interface.js +0 -129
  252. package/modules/repositories/module-repository-mongo.js +0 -408
  253. package/modules/repositories/module-repository-postgres.js +0 -453
  254. package/modules/repositories/module-repository.js +0 -345
  255. package/modules/requester/api-key.js +0 -52
  256. package/modules/requester/basic.js +0 -43
  257. package/modules/requester/oauth-2.js +0 -396
  258. package/modules/requester/requester.js +0 -167
  259. package/modules/use-cases/get-entities-for-user.js +0 -32
  260. package/modules/use-cases/get-entity-options-by-id.js +0 -71
  261. package/modules/use-cases/get-entity-options-by-type.js +0 -34
  262. package/modules/use-cases/get-module-instance-from-type.js +0 -31
  263. package/modules/use-cases/get-module.js +0 -74
  264. package/modules/use-cases/process-authorization-callback.js +0 -133
  265. package/modules/use-cases/refresh-entity-options.js +0 -72
  266. package/modules/use-cases/test-module-auth.js +0 -72
  267. package/modules/utils/map-module-dto.js +0 -18
  268. package/queues/index.js +0 -4
  269. package/queues/queuer-util.js +0 -66
  270. package/syncs/manager.js +0 -489
  271. package/syncs/repositories/sync-repository-documentdb.js +0 -240
  272. package/syncs/repositories/sync-repository-factory.js +0 -43
  273. package/syncs/repositories/sync-repository-interface.js +0 -109
  274. package/syncs/repositories/sync-repository-mongo.js +0 -239
  275. package/syncs/repositories/sync-repository-postgres.js +0 -319
  276. package/syncs/sync.js +0 -113
  277. package/token/repositories/token-repository-documentdb.js +0 -137
  278. package/token/repositories/token-repository-factory.js +0 -40
  279. package/token/repositories/token-repository-interface.js +0 -131
  280. package/token/repositories/token-repository-mongo.js +0 -219
  281. package/token/repositories/token-repository-postgres.js +0 -264
  282. package/token/repositories/token-repository.js +0 -219
  283. package/user/repositories/user-repository-documentdb.js +0 -441
  284. package/user/repositories/user-repository-factory.js +0 -52
  285. package/user/repositories/user-repository-interface.js +0 -201
  286. package/user/repositories/user-repository-mongo.js +0 -308
  287. package/user/repositories/user-repository-postgres.js +0 -360
  288. package/user/use-cases/authenticate-user.js +0 -127
  289. package/user/use-cases/authenticate-with-shared-secret.js +0 -48
  290. package/user/use-cases/create-individual-user.js +0 -61
  291. package/user/use-cases/create-organization-user.js +0 -47
  292. package/user/use-cases/create-token-for-user-id.js +0 -30
  293. package/user/use-cases/get-user-from-adopter-jwt.js +0 -149
  294. package/user/use-cases/get-user-from-bearer-token.js +0 -77
  295. package/user/use-cases/get-user-from-x-frigg-headers.js +0 -132
  296. package/user/use-cases/login-user.js +0 -122
  297. package/user/user.js +0 -125
  298. package/utils/backend-path.js +0 -6
  299. package/utils/index.js +0 -6
  300. package/websocket/repositories/websocket-connection-repository-documentdb.js +0 -119
  301. package/websocket/repositories/websocket-connection-repository-factory.js +0 -44
  302. package/websocket/repositories/websocket-connection-repository-interface.js +0 -106
  303. package/websocket/repositories/websocket-connection-repository-mongo.js +0 -156
  304. package/websocket/repositories/websocket-connection-repository-postgres.js +0 -196
  305. package/websocket/repositories/websocket-connection-repository.js +0 -161
@@ -0,0 +1,158 @@
1
+ jest.mock('../../database/config', () => {
2
+ const mockConfig = {
3
+ DB_TYPE: 'mongodb',
4
+ getDatabaseType: jest.fn(() => 'mongodb'),
5
+ PRISMA_LOG_LEVEL: 'error,warn',
6
+ PRISMA_QUERY_LOGGING: false,
7
+ };
8
+ return { __esModule: true, default: mockConfig, ...mockConfig };
9
+ });
10
+
11
+ jest.mock('../../integrations/repositories/integration-repository-factory', () => ({
12
+ createIntegrationRepository: jest.fn(() => ({
13
+ findIntegrationById: jest.fn(),
14
+ findIntegrationByUserId: jest.fn(),
15
+ findIntegrationsByUserId: jest.fn(),
16
+ createIntegration: jest.fn(),
17
+ updateIntegrationById: jest.fn(),
18
+ deleteIntegrationById: jest.fn(),
19
+ })),
20
+ }));
21
+
22
+ jest.mock('../../modules/repositories/module-repository-factory', () => ({
23
+ createModuleRepository: jest.fn(() => ({})),
24
+ }));
25
+
26
+ const mockFindExecute: any = jest.fn();
27
+
28
+ jest.mock('../../integrations/use-cases/find-integration-context-by-external-entity-id', () => {
29
+ return {
30
+ FindIntegrationContextByExternalEntityIdUseCase: jest
31
+ .fn()
32
+ .mockImplementation(() => ({
33
+ execute: mockFindExecute,
34
+ })),
35
+ };
36
+ });
37
+
38
+ import {
39
+ createIntegrationCommands,
40
+ findIntegrationContextByExternalEntityId,
41
+ } from './integration-commands';
42
+ import {
43
+ FindIntegrationContextByExternalEntityIdUseCase,
44
+ } from '../../integrations/use-cases/find-integration-context-by-external-entity-id';
45
+ import { DummyIntegration } from '../../integrations/tests/doubles/dummy-integration-class';
46
+
47
+ describe('integration commands', () => {
48
+ beforeEach(() => {
49
+ jest.clearAllMocks();
50
+ mockFindExecute.mockReset();
51
+ });
52
+
53
+ it('requires an integrationClass when creating commands', () => {
54
+ expect(() => createIntegrationCommands({} as any)).toThrow(
55
+ 'integrationClass is required',
56
+ );
57
+ });
58
+
59
+ it('creates use cases with default repositories', () => {
60
+ createIntegrationCommands({
61
+ integrationClass: DummyIntegration,
62
+ });
63
+
64
+ // Verify that the use case is created with default repositories instantiated internally
65
+ expect(
66
+ FindIntegrationContextByExternalEntityIdUseCase,
67
+ ).toHaveBeenCalledWith({
68
+ integrationRepository: expect.any(Object),
69
+ moduleRepository: expect.any(Object),
70
+ loadIntegrationContextUseCase: expect.any(Object),
71
+ });
72
+ });
73
+
74
+ it('returns context when findIntegrationContextByExternalEntityId succeeds', async () => {
75
+ const expectedContext = { record: { id: 'integration-1' } };
76
+ mockFindExecute.mockResolvedValue({ context: expectedContext });
77
+ const commands = createIntegrationCommands({
78
+ integrationClass: DummyIntegration,
79
+ });
80
+
81
+ const result = await commands.findIntegrationContextByExternalEntityId(
82
+ 'ext-1',
83
+ );
84
+
85
+ expect(mockFindExecute).toHaveBeenCalledWith({
86
+ externalEntityId: 'ext-1',
87
+ });
88
+ expect(result).toEqual({ context: expectedContext });
89
+ });
90
+
91
+ it('maps known errors to status codes', async () => {
92
+ const error = Object.assign(new Error('Entity missing'), {
93
+ code: 'ENTITY_NOT_FOUND',
94
+ });
95
+ mockFindExecute.mockRejectedValue(error);
96
+ const commands = createIntegrationCommands({
97
+ integrationClass: DummyIntegration,
98
+ });
99
+
100
+ const result = await commands.findIntegrationContextByExternalEntityId(
101
+ 'ext-1',
102
+ );
103
+
104
+ expect(result).toEqual({
105
+ error: 401,
106
+ reason: 'Entity missing',
107
+ code: 'ENTITY_NOT_FOUND',
108
+ });
109
+ });
110
+
111
+ it('delegates loadIntegrationContextById to the loader use case', async () => {
112
+ const commands = createIntegrationCommands({
113
+ integrationClass: DummyIntegration,
114
+ });
115
+
116
+ const result = await commands.loadIntegrationContextById('integration-1');
117
+
118
+ expect(result).toHaveProperty('error');
119
+ });
120
+
121
+ it('exposes a one-off helper for finding integration context by external entity id', async () => {
122
+ const expectedContext = { record: { id: 'integration-1' } };
123
+ mockFindExecute.mockResolvedValue({ context: expectedContext });
124
+
125
+ const result = await findIntegrationContextByExternalEntityId({
126
+ integrationClass: DummyIntegration,
127
+ externalEntityId: 'ext-2',
128
+ });
129
+
130
+ expect(mockFindExecute).toHaveBeenCalledWith({
131
+ externalEntityId: 'ext-2',
132
+ });
133
+ expect(result).toEqual({ context: expectedContext });
134
+ });
135
+
136
+ describe('deleteIntegrationById', () => {
137
+ it('returns error if integrationId is missing', async () => {
138
+ const commands = createIntegrationCommands({
139
+ integrationClass: DummyIntegration,
140
+ });
141
+
142
+ const result = await commands.deleteIntegrationById(null as any);
143
+
144
+ expect(result).toHaveProperty('error');
145
+ expect(result.reason).toContain('integrationId is required');
146
+ });
147
+
148
+ it('calls repository deleteIntegrationById', async () => {
149
+ const commands = createIntegrationCommands({
150
+ integrationClass: DummyIntegration,
151
+ });
152
+
153
+ const result = await commands.deleteIntegrationById('integration-123');
154
+
155
+ expect(result).toHaveProperty('error');
156
+ });
157
+ });
158
+ });
@@ -1,26 +1,11 @@
1
- /* eslint-disable @typescript-eslint/no-require-imports */
2
- const {
3
- createIntegrationRepository,
4
- } = require('../../../integrations/repositories/integration-repository-factory');
5
- const {
6
- createModuleRepository,
7
- } = require('../../../modules/repositories/module-repository-factory');
8
- const { ModuleFactory } = require('../../../modules/module-factory');
9
- const {
10
- LoadIntegrationContextUseCase,
11
- } = require('../../../integrations/use-cases/load-integration-context');
12
- const {
13
- FindIntegrationContextByExternalEntityIdUseCase,
14
- } = require('../../../integrations/use-cases/find-integration-context-by-external-entity-id');
15
- const {
16
- GetIntegrationsForUser,
17
- } = require('../../../integrations/use-cases/get-integrations-for-user');
18
- const {
19
- CreateIntegration,
20
- } = require('../../../integrations/use-cases/create-integration');
21
- const {
22
- getModulesDefinitionFromIntegrationClasses,
23
- } = require('../../../integrations/utils/map-integration-dto');
1
+ import { createIntegrationRepository } from '../../integrations/repositories/integration-repository-factory';
2
+ import { createModuleRepository } from '../../modules/repositories/module-repository-factory';
3
+ import { ModuleFactory } from '../../modules/module-factory';
4
+ import { LoadIntegrationContextUseCase } from '../../integrations/use-cases/load-integration-context';
5
+ import { FindIntegrationContextByExternalEntityIdUseCase } from '../../integrations/use-cases/find-integration-context-by-external-entity-id';
6
+ import { GetIntegrationsForUser } from '../../integrations/use-cases/get-integrations-for-user';
7
+ import { CreateIntegration } from '../../integrations/use-cases/create-integration';
8
+ import { getModulesDefinitionFromIntegrationClasses } from '../../integrations/utils/map-integration-dto';
24
9
 
25
10
  export interface IntegrationClass {
26
11
  name?: string;
@@ -84,7 +69,7 @@ function mapErrorToResponse(error: Error & { code?: string }): ErrorResponse {
84
69
  };
85
70
  }
86
71
 
87
- export function createIntegrationCommands({ integrationClass }: { integrationClass: IntegrationClass }): IntegrationCommands {
72
+ export function createIntegrationCommands({ integrationClass }: { integrationClass: IntegrationClass }): any {
88
73
  if (!integrationClass) {
89
74
  throw new Error('integrationClass is required');
90
75
  }
@@ -94,41 +79,41 @@ export function createIntegrationCommands({ integrationClass }: { integrationCla
94
79
 
95
80
  const moduleDefinitions = getModulesDefinitionFromIntegrationClasses([
96
81
  integrationClass,
97
- ]);
82
+ ] as any);
98
83
 
99
84
  const moduleFactory = new ModuleFactory({
100
- moduleRepository,
101
- moduleDefinitions,
85
+ moduleRepository: moduleRepository as any,
86
+ moduleDefinitions: moduleDefinitions as any,
102
87
  });
103
88
 
104
89
  const loadIntegrationContextUseCase = new LoadIntegrationContextUseCase({
105
90
  integrationRepository,
106
- moduleRepository,
91
+ moduleRepository: moduleRepository as any,
107
92
  moduleFactory,
108
93
  });
109
94
 
110
95
  const findByExternalEntityIdUseCase =
111
96
  new FindIntegrationContextByExternalEntityIdUseCase({
112
97
  integrationRepository,
113
- moduleRepository,
98
+ moduleRepository: moduleRepository as any,
114
99
  loadIntegrationContextUseCase: loadIntegrationContextUseCase,
115
100
  });
116
101
 
117
102
  const getIntegrationsForUserUseCase = new GetIntegrationsForUser({
118
103
  integrationRepository,
119
- integrationClasses: [integrationClass],
104
+ integrationClasses: [integrationClass] as any,
120
105
  moduleFactory,
121
- moduleRepository,
106
+ moduleRepository: moduleRepository as any,
122
107
  });
123
108
 
124
109
  const createIntegrationUseCase = new CreateIntegration({
125
110
  integrationRepository,
126
- integrationClasses: [integrationClass],
111
+ integrationClasses: [integrationClass] as any,
127
112
  moduleFactory,
128
113
  });
129
114
 
130
115
  return {
131
- async findIntegrationContextByExternalEntityId(externalEntityId: string) {
116
+ async findIntegrationContextByExternalEntityId(externalEntityId: string): Promise<any> {
132
117
  try {
133
118
  const { context } = await findByExternalEntityIdUseCase.execute(
134
119
  {
@@ -167,7 +152,7 @@ export function createIntegrationCommands({ integrationClass }: { integrationCla
167
152
  const integration = await createIntegrationUseCase.execute(
168
153
  entityIds,
169
154
  userId,
170
- config
155
+ config as any
171
156
  );
172
157
  return integration;
173
158
  } catch (error) {
@@ -177,7 +162,7 @@ export function createIntegrationCommands({ integrationClass }: { integrationCla
177
162
 
178
163
  async updateIntegrationConfig({ integrationId, config }: UpdateIntegrationConfigParams) {
179
164
  try {
180
- const integration = await integrationRepository.updateIntegrationConfig(
165
+ const integration = await (integrationRepository as any).updateIntegrationConfig(
181
166
  integrationId,
182
167
  config
183
168
  );
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Tests for Worker - AWS SDK v3 Migration
3
+ *
4
+ * Tests SQS Worker operations using aws-sdk-client-mock
5
+ */
6
+
7
+ import { mockClient } from 'aws-sdk-client-mock';
8
+ import { SQSClient, GetQueueUrlCommand, SendMessageCommand } from '@aws-sdk/client-sqs';
9
+ import { Worker } from './Worker';
10
+
11
+ describe('Worker - AWS SDK v3', () => {
12
+ let sqsMock: ReturnType<typeof mockClient>;
13
+ let worker: Worker;
14
+ const originalEnv = process.env;
15
+
16
+ beforeEach(() => {
17
+ sqsMock = mockClient(SQSClient);
18
+ worker = new Worker();
19
+ jest.clearAllMocks();
20
+ process.env = { ...originalEnv, AWS_REGION: 'us-east-1' };
21
+ });
22
+
23
+ afterEach(() => {
24
+ sqsMock.reset();
25
+ process.env = originalEnv;
26
+ });
27
+
28
+ describe('getQueueURL()', () => {
29
+ it('should get queue URL from SQS', async () => {
30
+ sqsMock.on(GetQueueUrlCommand).resolves({
31
+ QueueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/test-queue',
32
+ });
33
+
34
+ const result = await worker.getQueueURL({ QueueName: 'test-queue' });
35
+
36
+ expect(result).toBe('https://sqs.us-east-1.amazonaws.com/123456789/test-queue');
37
+ expect(sqsMock.calls()).toHaveLength(1);
38
+
39
+ const call = sqsMock.call(0);
40
+ expect(call.args[0].input).toMatchObject({
41
+ QueueName: 'test-queue',
42
+ });
43
+ });
44
+
45
+ it('should handle queue not found error', async () => {
46
+ sqsMock.on(GetQueueUrlCommand).rejects(new Error('Queue does not exist'));
47
+
48
+ await expect(worker.getQueueURL({ QueueName: 'nonexistent-queue' }))
49
+ .rejects.toThrow('Queue does not exist');
50
+ });
51
+ });
52
+
53
+ describe('sendAsyncSQSMessage()', () => {
54
+ it('should send message and return MessageId', async () => {
55
+ sqsMock.on(SendMessageCommand).resolves({
56
+ MessageId: 'message-123',
57
+ });
58
+
59
+ const params = {
60
+ QueueUrl: 'https://queue-url',
61
+ MessageBody: JSON.stringify({ test: 'data' }),
62
+ };
63
+
64
+ const result = await worker.sendAsyncSQSMessage(params);
65
+
66
+ expect(result).toBe('message-123');
67
+ expect(sqsMock.calls()).toHaveLength(1);
68
+ });
69
+
70
+ it('should handle send errors', async () => {
71
+ sqsMock.on(SendMessageCommand).rejects(new Error('Send failed'));
72
+
73
+ const params = {
74
+ QueueUrl: 'https://queue-url',
75
+ MessageBody: 'test',
76
+ };
77
+
78
+ await expect(worker.sendAsyncSQSMessage(params)).rejects.toThrow('Send failed');
79
+ });
80
+ });
81
+
82
+ describe('send()', () => {
83
+ it('should validate params and send message with delay', async () => {
84
+ sqsMock.on(SendMessageCommand).resolves({
85
+ MessageId: 'delayed-message-id',
86
+ });
87
+
88
+ worker._validateParams = jest.fn(); // Mock validation
89
+
90
+ const params = {
91
+ QueueUrl: 'https://queue-url',
92
+ data: 'test',
93
+ };
94
+
95
+ const result = await worker.send(params, 5);
96
+
97
+ expect(worker._validateParams).toHaveBeenCalledWith(params);
98
+ expect(result).toBe('delayed-message-id');
99
+
100
+ const call = sqsMock.call(0);
101
+ expect((call.args[0].input as any).DelaySeconds).toBe(5);
102
+ });
103
+
104
+ it('should send message with zero delay by default', async () => {
105
+ sqsMock.on(SendMessageCommand).resolves({
106
+ MessageId: 'message-id',
107
+ });
108
+
109
+ worker._validateParams = jest.fn();
110
+
111
+ const params = {
112
+ QueueUrl: 'https://queue-url',
113
+ data: 'test',
114
+ };
115
+
116
+ await worker.send(params);
117
+
118
+ const call = sqsMock.call(0);
119
+ expect((call.args[0].input as any).DelaySeconds).toBe(0);
120
+ });
121
+ });
122
+
123
+ describe('run()', () => {
124
+ it('should process SQS records', async () => {
125
+ worker._validateParams = jest.fn();
126
+ worker._run = jest.fn().mockResolvedValue(undefined);
127
+
128
+ const params = {
129
+ Records: [
130
+ { body: JSON.stringify({ task: 'test-1' }) },
131
+ { body: JSON.stringify({ task: 'test-2' }) },
132
+ ],
133
+ };
134
+
135
+ await worker.run(params);
136
+
137
+ expect(worker._run).toHaveBeenCalledTimes(2);
138
+ expect(worker._run).toHaveBeenCalledWith({ task: 'test-1' }, {});
139
+ expect(worker._run).toHaveBeenCalledWith({ task: 'test-2' }, {});
140
+ });
141
+
142
+ it('should pass context to _run method', async () => {
143
+ worker._validateParams = jest.fn();
144
+ worker._run = jest.fn().mockResolvedValue(undefined);
145
+
146
+ const params = {
147
+ Records: [
148
+ { body: JSON.stringify({ task: 'test' }) },
149
+ ],
150
+ };
151
+ const context = { userId: '123' };
152
+
153
+ await worker.run(params, context);
154
+
155
+ expect(worker._run).toHaveBeenCalledWith({ task: 'test' }, context);
156
+ });
157
+ });
158
+ });
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Tests for LambdaInvoker
3
+ * Infrastructure layer - AWS Lambda invocation adapter
4
+ */
5
+
6
+ import { LambdaInvoker, LambdaInvocationError } from './lambda-invoker';
7
+
8
+ describe('LambdaInvoker', () => {
9
+ let invoker: LambdaInvoker;
10
+ let mockLambdaClient: { send: jest.Mock };
11
+
12
+ beforeEach(() => {
13
+ mockLambdaClient = {
14
+ send: jest.fn(),
15
+ };
16
+ invoker = new LambdaInvoker(mockLambdaClient as any);
17
+ });
18
+
19
+ describe('invoke()', () => {
20
+ it('should invoke Lambda and return parsed result on success', async () => {
21
+ mockLambdaClient.send.mockResolvedValue({
22
+ Payload: Buffer.from(JSON.stringify({
23
+ statusCode: 200,
24
+ body: { upToDate: true, pendingMigrations: 0 },
25
+ })),
26
+ });
27
+
28
+ const result = await invoker.invoke('test-function', { action: 'checkStatus' });
29
+
30
+ expect(result).toEqual({ upToDate: true, pendingMigrations: 0 });
31
+ expect(mockLambdaClient.send).toHaveBeenCalledWith(
32
+ expect.objectContaining({
33
+ input: expect.objectContaining({
34
+ FunctionName: 'test-function',
35
+ InvocationType: 'RequestResponse',
36
+ Payload: JSON.stringify({ action: 'checkStatus' }),
37
+ }),
38
+ })
39
+ );
40
+ });
41
+
42
+ it('should throw LambdaInvocationError on Lambda error status', async () => {
43
+ mockLambdaClient.send.mockResolvedValue({
44
+ Payload: Buffer.from(JSON.stringify({
45
+ statusCode: 500,
46
+ body: { error: 'Database connection failed' },
47
+ })),
48
+ });
49
+
50
+ await expect(invoker.invoke('test-function', {}))
51
+ .rejects
52
+ .toThrow(LambdaInvocationError);
53
+
54
+ await expect(invoker.invoke('test-function', {}))
55
+ .rejects
56
+ .toThrow(/test-function/);
57
+
58
+ await expect(invoker.invoke('test-function', {}))
59
+ .rejects
60
+ .toThrow(/Database connection failed/);
61
+ });
62
+
63
+ it('should throw LambdaInvocationError on malformed response', async () => {
64
+ mockLambdaClient.send.mockResolvedValue({
65
+ Payload: Buffer.from('not json'),
66
+ });
67
+
68
+ await expect(invoker.invoke('test-function', {}))
69
+ .rejects
70
+ .toThrow(LambdaInvocationError);
71
+
72
+ await expect(invoker.invoke('test-function', {}))
73
+ .rejects
74
+ .toThrow(/Failed to parse/);
75
+ });
76
+
77
+ it('should handle AWS SDK errors', async () => {
78
+ mockLambdaClient.send.mockRejectedValue(new Error('AccessDenied: User not authorized'));
79
+
80
+ await expect(invoker.invoke('test-function', {}))
81
+ .rejects
82
+ .toThrow('Failed to invoke Lambda test-function: AccessDenied: User not authorized');
83
+ });
84
+
85
+ it('should include function name in LambdaInvocationError', async () => {
86
+ mockLambdaClient.send.mockResolvedValue({
87
+ Payload: Buffer.from(JSON.stringify({
88
+ statusCode: 500,
89
+ body: { error: 'Test error' },
90
+ })),
91
+ });
92
+
93
+ try {
94
+ await invoker.invoke('my-function-name', {});
95
+ fail('Should have thrown');
96
+ } catch (error: any) {
97
+ expect(error).toBeInstanceOf(LambdaInvocationError);
98
+ expect(error.functionName).toBe('my-function-name');
99
+ expect(error.statusCode).toBe(500);
100
+ expect(error.message).toContain('my-function-name');
101
+ }
102
+ });
103
+ });
104
+ });