@friggframework/core 2.0.0-next.12 → 2.0.0-next.121

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 (410) hide show
  1. package/.eslintrc.json +18 -1
  2. package/CLAUDE.md +830 -0
  3. package/README.md +996 -50
  4. package/admin-scripts/index.js +52 -0
  5. package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
  6. package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
  7. package/admin-scripts/repositories/admin-script-execution-repository-interface.js +171 -0
  8. package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +238 -0
  9. package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +278 -0
  10. package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
  11. package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
  12. package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
  13. package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
  14. package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
  15. package/application/commands/README.md +451 -0
  16. package/application/commands/admin-script-commands.js +359 -0
  17. package/application/commands/credential-commands.js +262 -0
  18. package/application/commands/entity-commands.js +294 -0
  19. package/application/commands/integration-commands.js +419 -0
  20. package/application/commands/integration-mapping-commands.js +25 -0
  21. package/application/commands/process-commands.js +135 -0
  22. package/application/commands/report-commands.js +188 -0
  23. package/application/commands/scheduler-commands.js +263 -0
  24. package/application/commands/usage-commands.js +56 -0
  25. package/application/commands/user-commands.js +312 -0
  26. package/application/index.js +83 -0
  27. package/artifacts/repositories/artifact-repository-factory.js +19 -0
  28. package/artifacts/repositories/artifact-repository-interface.js +27 -0
  29. package/artifacts/repositories/artifact-repository-local.js +42 -0
  30. package/artifacts/repositories/artifact-repository-s3.js +61 -0
  31. package/assertions/index.js +0 -3
  32. package/core/CLAUDE.md +715 -0
  33. package/core/Worker.js +55 -24
  34. package/core/create-handler.js +121 -38
  35. package/core/index.js +8 -1
  36. package/core/invocation-scope.js +225 -0
  37. package/core/parameters-to-env.js +257 -0
  38. package/core/secrets-to-env.js +7 -6
  39. package/core/ssm-preload.mjs +34 -0
  40. package/credential/repositories/credential-active-type.js +32 -0
  41. package/credential/repositories/credential-repository-documentdb.js +355 -0
  42. package/credential/repositories/credential-repository-factory.js +54 -0
  43. package/credential/repositories/credential-repository-interface.js +113 -0
  44. package/credential/repositories/credential-repository-mongo.js +294 -0
  45. package/credential/repositories/credential-repository-postgres.js +312 -0
  46. package/credential/repositories/credential-repository.js +300 -0
  47. package/credential/use-cases/get-credential-for-user.js +25 -0
  48. package/credential/use-cases/update-authentication-status.js +15 -0
  49. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  50. package/database/adapters/lambda-invoker.js +97 -0
  51. package/database/config.js +147 -0
  52. package/database/documentdb-encryption-service.js +334 -0
  53. package/database/documentdb-utils.js +196 -0
  54. package/database/encryption/README.md +863 -0
  55. package/database/encryption/documentdb-encryption-service.md +3575 -0
  56. package/database/encryption/encryption-schema-registry.js +404 -0
  57. package/database/encryption/field-encryption-service.js +254 -0
  58. package/database/encryption/integration-mapping-encryption.js +97 -0
  59. package/database/encryption/logger.js +82 -0
  60. package/database/encryption/prisma-encryption-extension.js +241 -0
  61. package/database/index.js +21 -21
  62. package/database/prisma.js +182 -0
  63. package/database/repositories/health-check-repository-documentdb.js +138 -0
  64. package/database/repositories/health-check-repository-factory.js +48 -0
  65. package/database/repositories/health-check-repository-interface.js +82 -0
  66. package/database/repositories/health-check-repository-mongodb.js +89 -0
  67. package/database/repositories/health-check-repository-postgres.js +82 -0
  68. package/database/repositories/migration-status-repository-s3.js +137 -0
  69. package/database/use-cases/check-database-health-use-case.js +29 -0
  70. package/database/use-cases/check-database-state-use-case.js +81 -0
  71. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  72. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  73. package/database/use-cases/get-migration-status-use-case.js +93 -0
  74. package/database/use-cases/resolve-migration-via-worker-use-case.js +49 -0
  75. package/database/use-cases/run-database-migration-use-case.js +139 -0
  76. package/database/use-cases/test-encryption-use-case.js +253 -0
  77. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  78. package/database/utils/mongodb-collection-utils.js +94 -0
  79. package/database/utils/mongodb-schema-init.js +108 -0
  80. package/database/utils/prisma-runner.js +491 -0
  81. package/database/utils/prisma-schema-parser.js +182 -0
  82. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  83. package/encrypt/Cryptor.js +34 -168
  84. package/encrypt/index.js +1 -2
  85. package/errors/client-safe-error.js +26 -0
  86. package/errors/fetch-error.js +59 -57
  87. package/errors/index.js +6 -0
  88. package/errors/mapping-already-exists-error.js +14 -0
  89. package/generated/prisma-mongodb/client.d.ts +1 -0
  90. package/generated/prisma-mongodb/client.js +5 -0
  91. package/generated/prisma-mongodb/default.d.ts +1 -0
  92. package/generated/prisma-mongodb/default.js +5 -0
  93. package/generated/prisma-mongodb/edge.d.ts +1 -0
  94. package/generated/prisma-mongodb/edge.js +386 -0
  95. package/generated/prisma-mongodb/index-browser.js +368 -0
  96. package/generated/prisma-mongodb/index.d.ts +27065 -0
  97. package/generated/prisma-mongodb/index.js +411 -0
  98. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  99. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  100. package/generated/prisma-mongodb/package.json +183 -0
  101. package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
  102. package/generated/prisma-mongodb/runtime/edge.js +35 -0
  103. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  104. package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
  105. package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
  106. package/generated/prisma-mongodb/runtime/library.js +147 -0
  107. package/generated/prisma-mongodb/runtime/react-native.js +84 -0
  108. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
  109. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
  110. package/generated/prisma-mongodb/schema.prisma +455 -0
  111. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
  112. package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
  113. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  114. package/generated/prisma-mongodb/wasm.js +393 -0
  115. package/generated/prisma-postgresql/client.d.ts +1 -0
  116. package/generated/prisma-postgresql/client.js +5 -0
  117. package/generated/prisma-postgresql/default.d.ts +1 -0
  118. package/generated/prisma-postgresql/default.js +5 -0
  119. package/generated/prisma-postgresql/edge.d.ts +1 -0
  120. package/generated/prisma-postgresql/edge.js +407 -0
  121. package/generated/prisma-postgresql/index-browser.js +389 -0
  122. package/generated/prisma-postgresql/index.d.ts +29904 -0
  123. package/generated/prisma-postgresql/index.js +432 -0
  124. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  125. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  126. package/generated/prisma-postgresql/package.json +183 -0
  127. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  128. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  129. package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
  130. package/generated/prisma-postgresql/runtime/edge.js +35 -0
  131. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  132. package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
  133. package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
  134. package/generated/prisma-postgresql/runtime/library.js +147 -0
  135. package/generated/prisma-postgresql/runtime/react-native.js +84 -0
  136. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
  137. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
  138. package/generated/prisma-postgresql/schema.prisma +436 -0
  139. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
  140. package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
  141. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  142. package/generated/prisma-postgresql/wasm.js +414 -0
  143. package/handlers/WEBHOOKS.md +682 -0
  144. package/handlers/app-definition-loader.js +103 -0
  145. package/handlers/app-handler-helpers.js +20 -6
  146. package/handlers/backend-utils.js +272 -46
  147. package/handlers/database-migration-handler.js +236 -0
  148. package/handlers/integration-event-dispatcher.js +68 -0
  149. package/handlers/middleware/admin-auth.js +73 -0
  150. package/handlers/routers/HEALTHCHECK.md +342 -0
  151. package/handlers/routers/auth.js +4 -15
  152. package/handlers/routers/db-migration.handler.js +29 -0
  153. package/handlers/routers/db-migration.js +329 -0
  154. package/handlers/routers/health.js +518 -0
  155. package/handlers/routers/integration-defined-routers.js +85 -10
  156. package/handlers/routers/integration-webhook-routers.js +87 -0
  157. package/handlers/routers/user.js +27 -5
  158. package/handlers/routers/websocket.js +31 -9
  159. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  160. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  161. package/handlers/workers/db-migration.js +438 -0
  162. package/handlers/workers/dlq-processor.js +89 -0
  163. package/handlers/workers/integration-defined-workers.js +13 -7
  164. package/index.js +123 -47
  165. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +238 -0
  166. package/infrastructure/scheduler/index.js +33 -0
  167. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  168. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  169. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  170. package/integrations/EXTENSIONS.md +240 -0
  171. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  172. package/integrations/extension.js +254 -0
  173. package/integrations/index.js +20 -10
  174. package/integrations/integration-base.js +777 -74
  175. package/integrations/integration-router.js +399 -180
  176. package/integrations/options.js +1 -1
  177. package/integrations/repositories/config-patch-shared.js +43 -0
  178. package/integrations/repositories/integration-mapping-query-pipeline.js +152 -0
  179. package/integrations/repositories/integration-mapping-query.js +193 -0
  180. package/integrations/repositories/integration-mapping-repository-documentdb.js +406 -0
  181. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  182. package/integrations/repositories/integration-mapping-repository-interface.js +183 -0
  183. package/integrations/repositories/integration-mapping-repository-mongo.js +284 -0
  184. package/integrations/repositories/integration-mapping-repository-postgres.js +403 -0
  185. package/integrations/repositories/integration-mapping-repository.js +185 -0
  186. package/integrations/repositories/integration-repository-documentdb.js +354 -0
  187. package/integrations/repositories/integration-repository-factory.js +51 -0
  188. package/integrations/repositories/integration-repository-interface.js +219 -0
  189. package/integrations/repositories/integration-repository-mongo.js +502 -0
  190. package/integrations/repositories/integration-repository-postgres.js +550 -0
  191. package/integrations/repositories/process-repository-documentdb.js +311 -0
  192. package/integrations/repositories/process-repository-factory.js +53 -0
  193. package/integrations/repositories/process-repository-interface.js +136 -0
  194. package/integrations/repositories/process-repository-mongo.js +262 -0
  195. package/integrations/repositories/process-repository-postgres.js +380 -0
  196. package/integrations/repositories/process-update-ops-shared.js +112 -0
  197. package/integrations/repositories/report-id.js +13 -0
  198. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  199. package/integrations/tests/doubles/dummy-integration-class.js +113 -0
  200. package/integrations/tests/doubles/test-integration-repository.js +146 -0
  201. package/integrations/use-cases/add-entities-to-integration.js +92 -0
  202. package/integrations/use-cases/create-integration.js +253 -0
  203. package/integrations/use-cases/create-process.js +130 -0
  204. package/integrations/use-cases/delete-integration-for-user.js +130 -0
  205. package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
  206. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
  207. package/integrations/use-cases/get-integration-for-user.js +78 -0
  208. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  209. package/integrations/use-cases/get-integration-instance.js +83 -0
  210. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  211. package/integrations/use-cases/get-possible-integrations.js +27 -0
  212. package/integrations/use-cases/get-process.js +89 -0
  213. package/integrations/use-cases/index.js +19 -0
  214. package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
  215. package/integrations/use-cases/load-integration-context.js +71 -0
  216. package/integrations/use-cases/patch-integration-config.js +39 -0
  217. package/integrations/use-cases/process-errors.js +28 -0
  218. package/integrations/use-cases/remove-entities-from-integration.js +70 -0
  219. package/integrations/use-cases/update-integration-config.js +32 -0
  220. package/integrations/use-cases/update-integration-messages.js +44 -0
  221. package/integrations/use-cases/update-integration-status.js +32 -0
  222. package/integrations/use-cases/update-integration.js +92 -0
  223. package/integrations/use-cases/update-process-metrics.js +222 -0
  224. package/integrations/use-cases/update-process-state.js +163 -0
  225. package/integrations/utils/assert-entity-ids-input.js +42 -0
  226. package/integrations/utils/map-integration-dto.js +37 -0
  227. package/jest-global-setup-noop.js +3 -0
  228. package/jest-global-teardown-noop.js +3 -0
  229. package/jest.config.js +2 -0
  230. package/logs/.eslintrc.json +26 -1
  231. package/logs/__fixtures__/events.js +82 -0
  232. package/logs/__fixtures__/matchers.js +45 -0
  233. package/logs/__fixtures__/secrets.js +59 -0
  234. package/logs/__fixtures__/vectors.js +329 -0
  235. package/logs/__fixtures__/with-env.js +45 -0
  236. package/logs/context.js +109 -0
  237. package/logs/contract-keys.js +67 -0
  238. package/logs/debug-shims.js +46 -0
  239. package/logs/denied-keys.js +21 -0
  240. package/logs/index.js +14 -3
  241. package/logs/jest-logger-setup.js +25 -0
  242. package/logs/levels.js +71 -0
  243. package/logs/logger-runtime.js +137 -0
  244. package/logs/logger.js +134 -46
  245. package/logs/record.js +276 -0
  246. package/logs/redact.js +328 -0
  247. package/logs/serialize.js +329 -0
  248. package/logs/sinks.js +93 -0
  249. package/logs/summarize-event.js +163 -0
  250. package/{module-plugin → modules}/index.js +0 -10
  251. package/modules/module-factory.js +56 -0
  252. package/modules/module.js +320 -0
  253. package/modules/repositories/module-repository-documentdb.js +350 -0
  254. package/modules/repositories/module-repository-factory.js +40 -0
  255. package/modules/repositories/module-repository-interface.js +145 -0
  256. package/modules/repositories/module-repository-mongo.js +436 -0
  257. package/modules/repositories/module-repository-postgres.js +481 -0
  258. package/modules/repositories/module-repository.js +369 -0
  259. package/modules/requester/api-key.js +52 -0
  260. package/modules/requester/oauth-2.js +561 -0
  261. package/modules/requester/requester.js +605 -0
  262. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  263. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  264. package/modules/tests/doubles/test-module-factory.js +16 -0
  265. package/modules/tests/doubles/test-module-repository.js +39 -0
  266. package/modules/use-cases/get-entities-for-user.js +32 -0
  267. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  268. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  269. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  270. package/modules/use-cases/get-module.js +74 -0
  271. package/modules/use-cases/process-authorization-callback.js +294 -0
  272. package/modules/use-cases/refresh-entity-options.js +72 -0
  273. package/modules/use-cases/test-module-auth.js +72 -0
  274. package/modules/utils/map-module-dto.js +20 -0
  275. package/modules/utils/to-credential-id.js +14 -0
  276. package/package.json +92 -52
  277. package/prisma-mongodb/schema.prisma +455 -0
  278. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  279. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  280. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  281. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  282. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  283. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  284. package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
  285. package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
  286. package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
  287. package/prisma-postgresql/migrations/20260705000000_create_usage_counter/migration.sql +26 -0
  288. package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
  289. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  290. package/prisma-postgresql/schema.prisma +436 -0
  291. package/queues/queue-delivery.js +41 -0
  292. package/queues/queuer-util.js +89 -21
  293. package/reporting/README.md +154 -0
  294. package/reporting/builtin-reports.js +6 -0
  295. package/reporting/index.js +13 -0
  296. package/reporting/report-base.js +49 -0
  297. package/reporting/reports/integrations-report.js +221 -0
  298. package/syncs/manager.js +468 -443
  299. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  300. package/syncs/repositories/sync-repository-factory.js +43 -0
  301. package/syncs/repositories/sync-repository-interface.js +109 -0
  302. package/syncs/repositories/sync-repository-mongo.js +239 -0
  303. package/syncs/repositories/sync-repository-postgres.js +319 -0
  304. package/syncs/sync.js +0 -1
  305. package/telemetry/README.md +331 -0
  306. package/telemetry/bind-telemetry-context.js +77 -0
  307. package/telemetry/canonical-counters.js +52 -0
  308. package/telemetry/exporters.js +85 -0
  309. package/telemetry/index.js +26 -0
  310. package/telemetry/instrument-handler.js +104 -0
  311. package/telemetry/no-op-telemetry.js +71 -0
  312. package/telemetry/north-star.js +103 -0
  313. package/telemetry/otel-telemetry.js +232 -0
  314. package/telemetry/plugin-subscribers.js +77 -0
  315. package/telemetry/telemetry-config.js +120 -0
  316. package/telemetry/telemetry-context.js +51 -0
  317. package/telemetry/telemetry-event-bus.js +58 -0
  318. package/telemetry/telemetry-runtime.js +164 -0
  319. package/telemetry/telemetry-service.js +52 -0
  320. package/telemetry/usage-rollup-subscriber.js +116 -0
  321. package/token/repositories/token-repository-documentdb.js +137 -0
  322. package/token/repositories/token-repository-factory.js +40 -0
  323. package/token/repositories/token-repository-interface.js +131 -0
  324. package/token/repositories/token-repository-mongo.js +219 -0
  325. package/token/repositories/token-repository-postgres.js +264 -0
  326. package/token/repositories/token-repository.js +219 -0
  327. package/types/associations/index.d.ts +0 -17
  328. package/types/core/index.d.ts +12 -4
  329. package/types/database/index.d.ts +10 -2
  330. package/types/encrypt/index.d.ts +5 -3
  331. package/types/errors/index.d.ts +24 -10
  332. package/types/integrations/index.d.ts +3 -8
  333. package/types/logs/index.d.ts +61 -2
  334. package/types/module-plugin/index.d.ts +20 -69
  335. package/types/syncs/index.d.ts +0 -17
  336. package/usage/README.md +54 -0
  337. package/usage/index.js +17 -0
  338. package/usage/repositories/usage-repository-documentdb.js +194 -0
  339. package/usage/repositories/usage-repository-factory.js +25 -0
  340. package/usage/repositories/usage-repository-interface.js +37 -0
  341. package/usage/repositories/usage-repository-prisma.js +146 -0
  342. package/usage/tracked-metrics.js +38 -0
  343. package/usage/usage-windows.js +24 -0
  344. package/user/repositories/user-repository-documentdb.js +426 -0
  345. package/user/repositories/user-repository-factory.js +52 -0
  346. package/user/repositories/user-repository-interface.js +214 -0
  347. package/user/repositories/user-repository-mongo.js +323 -0
  348. package/user/repositories/user-repository-postgres.js +377 -0
  349. package/user/tests/doubles/test-user-repository.js +72 -0
  350. package/user/use-cases/authenticate-user.js +143 -0
  351. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  352. package/user/use-cases/create-individual-user.js +61 -0
  353. package/user/use-cases/create-organization-user.js +47 -0
  354. package/user/use-cases/create-token-for-user-id.js +30 -0
  355. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  356. package/user/use-cases/get-user-from-bearer-token.js +82 -0
  357. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  358. package/user/use-cases/login-user.js +122 -0
  359. package/user/user.js +125 -0
  360. package/utils/backend-path.js +38 -0
  361. package/utils/index.js +6 -0
  362. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  363. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  364. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  365. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  366. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  367. package/websocket/repositories/websocket-connection-repository.js +161 -0
  368. package/assertions/is-equal.js +0 -17
  369. package/associations/model.js +0 -54
  370. package/database/models/IndividualUser.js +0 -76
  371. package/database/models/OrganizationUser.js +0 -29
  372. package/database/models/State.js +0 -9
  373. package/database/models/Token.js +0 -70
  374. package/database/models/UserModel.js +0 -7
  375. package/database/models/WebsocketConnection.js +0 -49
  376. package/database/mongo.js +0 -45
  377. package/database/mongoose.js +0 -5
  378. package/encrypt/Cryptor.test.js +0 -32
  379. package/encrypt/encrypt.js +0 -132
  380. package/encrypt/encrypt.test.js +0 -1069
  381. package/encrypt/test-encrypt.js +0 -107
  382. package/errors/base-error.test.js +0 -32
  383. package/errors/fetch-error.test.js +0 -79
  384. package/errors/halt-error.test.js +0 -11
  385. package/errors/validation-errors.test.js +0 -120
  386. package/handlers/routers/middleware/loadUser.js +0 -15
  387. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  388. package/integrations/create-frigg-backend.js +0 -31
  389. package/integrations/integration-factory.js +0 -251
  390. package/integrations/integration-mapping.js +0 -43
  391. package/integrations/integration-model.js +0 -46
  392. package/integrations/integration-user.js +0 -144
  393. package/integrations/test/integration-base.test.js +0 -144
  394. package/lambda/TimeoutCatcher.test.js +0 -68
  395. package/logs/logger.test.js +0 -76
  396. package/module-plugin/auther.js +0 -393
  397. package/module-plugin/credential.js +0 -22
  398. package/module-plugin/entity-manager.js +0 -70
  399. package/module-plugin/entity.js +0 -46
  400. package/module-plugin/manager.js +0 -169
  401. package/module-plugin/module-factory.js +0 -61
  402. package/module-plugin/requester/api-key.js +0 -36
  403. package/module-plugin/requester/oauth-2.js +0 -219
  404. package/module-plugin/requester/requester.js +0 -165
  405. package/module-plugin/requester/requester.test.js +0 -28
  406. package/module-plugin/test/auther.test.js +0 -97
  407. package/syncs/model.js +0 -62
  408. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  409. /package/{module-plugin → modules}/requester/basic.js +0 -0
  410. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,185 @@
1
+ const { prisma } = require('../../database/prisma');
2
+ const { MappingAlreadyExistsError } = require('../../errors');
3
+ const {
4
+ IntegrationMappingRepositoryInterface,
5
+ } = require('./integration-mapping-repository-interface');
6
+
7
+ /**
8
+ * Prisma-based Integration Mapping Repository
9
+ * Handles persistence of integration mappings used for data transformation
10
+ *
11
+ * Works identically for both MongoDB and PostgreSQL:
12
+ * - MongoDB: String IDs with @db.ObjectId
13
+ * - PostgreSQL: Integer IDs with auto-increment
14
+ * - Both use same query patterns (no many-to-many differences)
15
+ *
16
+ * Migration from Mongoose:
17
+ * - Constructor injection of Prisma client
18
+ * - IntegrationMapping.findBy() → findFirst with where clause
19
+ * - IntegrationMapping.upsert() → Prisma upsert with unique constraint
20
+ * - mapping data stored in JSON field
21
+ */
22
+ class IntegrationMappingRepository extends IntegrationMappingRepositoryInterface {
23
+ constructor(prismaClient = prisma) {
24
+ super();
25
+ this.prisma = prismaClient; // Allow injection for testing
26
+ }
27
+
28
+ /**
29
+ * Find mapping by integration ID and source ID
30
+ * Replaces: IntegrationMapping.findBy(integrationId, sourceId)
31
+ *
32
+ * @param {string} integrationId - The integration ID
33
+ * @param {string} sourceId - The source ID for lookup
34
+ * @returns {Promise<Object|null>} The mapping object or null
35
+ */
36
+ async findMappingBy(integrationId, sourceId) {
37
+ return await this.prisma.integrationMapping.findFirst({
38
+ where: {
39
+ integrationId,
40
+ sourceId,
41
+ },
42
+ });
43
+ }
44
+
45
+ /**
46
+ * Create or update a mapping
47
+ * Replaces: IntegrationMapping.upsert(integrationId, sourceId, mapping)
48
+ *
49
+ * @param {string} integrationId - The integration ID
50
+ * @param {string} sourceId - The source ID for lookup
51
+ * @param {Object} mapping - The mapping data
52
+ * @returns {Promise<Object>} The created or updated mapping document
53
+ */
54
+ async upsertMapping(integrationId, sourceId, mapping) {
55
+ return await this.prisma.integrationMapping.upsert({
56
+ where: {
57
+ integrationId_sourceId: {
58
+ integrationId,
59
+ sourceId,
60
+ },
61
+ },
62
+ update: {
63
+ mapping,
64
+ },
65
+ create: {
66
+ integrationId,
67
+ sourceId,
68
+ mapping,
69
+ },
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Insert a mapping; fails if (integrationId, sourceId) already exists
75
+ *
76
+ * @param {string} integrationId - The integration ID
77
+ * @param {string} sourceId - The source ID
78
+ * @param {Object} mapping - The mapping data
79
+ * @returns {Promise<Object>} The created mapping document
80
+ * @throws {MappingAlreadyExistsError} If the pair already exists
81
+ */
82
+ async createMapping(integrationId, sourceId, mapping) {
83
+ try {
84
+ return await this.prisma.integrationMapping.create({
85
+ data: {
86
+ integrationId,
87
+ sourceId,
88
+ mapping,
89
+ },
90
+ });
91
+ } catch (error) {
92
+ if (error.code === 'P2002') {
93
+ throw new MappingAlreadyExistsError(integrationId, sourceId, {
94
+ cause: error,
95
+ });
96
+ }
97
+ throw error;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Find all mappings for an integration
103
+ * Replaces: IntegrationMapping.find({ integration: integrationId })
104
+ *
105
+ * @param {string} integrationId - The integration ID
106
+ * @returns {Promise<Array>} Array of mapping documents
107
+ */
108
+ async findMappingsByIntegration(integrationId) {
109
+ return await this.prisma.integrationMapping.findMany({
110
+ where: { integrationId },
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Delete a mapping by integration and source ID
116
+ * Replaces: IntegrationMapping.deleteOne({ integration, sourceId })
117
+ *
118
+ * @param {string} integrationId - The integration ID
119
+ * @param {string} sourceId - The source ID
120
+ * @returns {Promise<Object>} The deletion result
121
+ */
122
+ async deleteMapping(integrationId, sourceId) {
123
+ try {
124
+ await this.prisma.integrationMapping.delete({
125
+ where: {
126
+ integrationId_sourceId: {
127
+ integrationId,
128
+ sourceId,
129
+ },
130
+ },
131
+ });
132
+ return { acknowledged: true, deletedCount: 1 };
133
+ } catch (error) {
134
+ if (error.code === 'P2025') {
135
+ // Record not found
136
+ return { acknowledged: true, deletedCount: 0 };
137
+ }
138
+ throw error;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Delete all mappings for an integration
144
+ * Replaces: IntegrationMapping.deleteMany({ integration: integrationId })
145
+ *
146
+ * @param {string} integrationId - The integration ID
147
+ * @returns {Promise<Object>} The deletion result
148
+ */
149
+ async deleteMappingsByIntegration(integrationId) {
150
+ const result = await this.prisma.integrationMapping.deleteMany({
151
+ where: { integrationId },
152
+ });
153
+
154
+ return {
155
+ acknowledged: true,
156
+ deletedCount: result.count,
157
+ };
158
+ }
159
+
160
+ /**
161
+ * Find mapping by ID
162
+ * @param {string} id - Mapping ID
163
+ * @returns {Promise<Object|null>} Mapping object or null
164
+ */
165
+ async findMappingById(id) {
166
+ return await this.prisma.integrationMapping.findUnique({
167
+ where: { id },
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Update mapping by ID
173
+ * @param {string} id - Mapping ID
174
+ * @param {Object} updates - Fields to update
175
+ * @returns {Promise<Object>} Updated mapping object
176
+ */
177
+ async updateMapping(id, updates) {
178
+ return await this.prisma.integrationMapping.update({
179
+ where: { id },
180
+ data: updates,
181
+ });
182
+ }
183
+ }
184
+
185
+ module.exports = { IntegrationMappingRepository };
@@ -0,0 +1,354 @@
1
+ const { prisma } = require('../../database/prisma');
2
+ const {
3
+ toObjectId,
4
+ toObjectIdArray,
5
+ fromObjectId,
6
+ findMany,
7
+ findManyDrained,
8
+ findOne,
9
+ insertOne,
10
+ updateOne,
11
+ deleteOne,
12
+ } = require('../../database/documentdb-utils');
13
+ const {
14
+ IntegrationRepositoryInterface,
15
+ } = require('./integration-repository-interface');
16
+ const { validateConfigPatch } = require('./config-patch-shared');
17
+
18
+ class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
19
+ constructor() {
20
+ super();
21
+ this.prisma = prisma;
22
+ }
23
+
24
+ async findIntegrationsByUserId(userId) {
25
+ const objectId = toObjectId(userId);
26
+ const filter = objectId ? { userId: objectId } : {};
27
+ const records = await findMany(this.prisma, 'Integration', filter);
28
+ return records.map((doc) => this._mapIntegration(doc));
29
+ }
30
+
31
+ async findIntegrations({ type, status } = {}) {
32
+ const filter = {};
33
+ if (type) {
34
+ filter['config.type'] = type;
35
+ }
36
+ if (status) {
37
+ filter.status = status;
38
+ }
39
+ const records = await findMany(this.prisma, 'Integration', filter);
40
+ return records.map((doc) => this._mapIntegration(doc));
41
+ }
42
+
43
+ async findIntegrationsByEntityId(entityId) {
44
+ const objectId = toObjectId(entityId);
45
+ if (!objectId) return [];
46
+ const records = await findMany(this.prisma, 'Integration', {
47
+ entityIds: objectId,
48
+ });
49
+ return records.map((doc) => this._mapIntegration(doc));
50
+ }
51
+
52
+ async deleteIntegrationById(integrationId) {
53
+ const objectId = toObjectId(integrationId);
54
+ if (!objectId) return { acknowledged: true, deletedCount: 0 };
55
+ const result = await deleteOne(this.prisma, 'Integration', { _id: objectId });
56
+ const deleted = result?.n ?? 0;
57
+ return { acknowledged: true, deletedCount: deleted };
58
+ }
59
+
60
+ async findIntegrationByName(name) {
61
+ const doc = await findOne(this.prisma, 'Integration', { 'config.type': name });
62
+ if (!doc) {
63
+ throw new Error(`Integration with name ${name} not found`);
64
+ }
65
+ return this._mapIntegration(doc);
66
+ }
67
+
68
+ async findIntegrationById(id) {
69
+ const objectId = toObjectId(id);
70
+ if (!objectId) {
71
+ throw new Error(`Integration with id ${id} not found`);
72
+ }
73
+ const doc = await findOne(this.prisma, 'Integration', { _id: objectId });
74
+ if (!doc) {
75
+ throw new Error(`Integration with id ${id} not found`);
76
+ }
77
+ return this._mapIntegration(doc);
78
+ }
79
+
80
+ async updateIntegrationStatus(integrationId, status) {
81
+ const objectId = toObjectId(integrationId);
82
+ if (!objectId) return false;
83
+ await updateOne(
84
+ this.prisma,
85
+ 'Integration',
86
+ { _id: objectId },
87
+ {
88
+ $set: { status, updatedAt: new Date() },
89
+ }
90
+ );
91
+ return true;
92
+ }
93
+
94
+ async updateIntegrationMessages(
95
+ integrationId,
96
+ messageType,
97
+ messageTitle,
98
+ messageBody,
99
+ messageTimestamp
100
+ ) {
101
+ const objectId = toObjectId(integrationId);
102
+ if (!objectId) {
103
+ throw new Error(`Integration ${integrationId} not found`);
104
+ }
105
+ const existing = await findOne(this.prisma, 'Integration', { _id: objectId });
106
+ if (!existing) {
107
+ throw new Error(`Integration ${integrationId} not found`);
108
+ }
109
+ const messages = this._extractMessages(existing);
110
+ const list = Array.isArray(messages[messageType]) ? [...messages[messageType]] : [];
111
+ list.push({
112
+ title: messageTitle ?? null,
113
+ message: messageBody,
114
+ timestamp: messageTimestamp,
115
+ });
116
+ const updatedMessages = { ...messages, [messageType]: list };
117
+ await updateOne(
118
+ this.prisma,
119
+ 'Integration',
120
+ { _id: objectId },
121
+ {
122
+ $set: {
123
+ messages: updatedMessages,
124
+ errors: updatedMessages.errors ?? [],
125
+ warnings: updatedMessages.warnings ?? [],
126
+ info: updatedMessages.info ?? [],
127
+ logs: updatedMessages.logs ?? [],
128
+ updatedAt: new Date(),
129
+ },
130
+ }
131
+ );
132
+ return true;
133
+ }
134
+
135
+ async createIntegration(entities, userId, config) {
136
+ const now = new Date();
137
+ const document = {
138
+ userId: toObjectId(userId) || null,
139
+ config,
140
+ version: '0.0.0',
141
+ status: 'IN_CREATION',
142
+ entityIds: toObjectIdArray(entities),
143
+ messages: { errors: [], warnings: [], info: [], logs: [] },
144
+ errors: [],
145
+ warnings: [],
146
+ info: [],
147
+ logs: [],
148
+ createdAt: now,
149
+ updatedAt: now,
150
+ };
151
+ const insertedId = await insertOne(this.prisma, 'Integration', document);
152
+ const created = await findOne(this.prisma, 'Integration', { _id: insertedId });
153
+ if (!created) {
154
+ console.error('[IntegrationRepositoryDocumentDB] Integration not found after insert', {
155
+ insertedId: fromObjectId(insertedId),
156
+ userId,
157
+ config,
158
+ });
159
+ throw new Error(
160
+ 'Failed to create integration: Document not found after insert. ' +
161
+ 'This indicates a database consistency issue.'
162
+ );
163
+ }
164
+ return this._mapIntegration(created);
165
+ }
166
+
167
+ async addEntitiesToIntegration(integrationId, entityIds) {
168
+ const objectId = toObjectId(integrationId);
169
+ if (!objectId) return null;
170
+ const result = await updateOne(
171
+ this.prisma,
172
+ 'Integration',
173
+ { _id: objectId },
174
+ {
175
+ $addToSet: { entityIds: { $each: toObjectIdArray(entityIds) } },
176
+ $set: { updatedAt: { $date: new Date().toISOString() } },
177
+ }
178
+ );
179
+ if (!result?.n) return null;
180
+ return this.findIntegrationById(integrationId);
181
+ }
182
+
183
+ async removeEntitiesFromIntegration(integrationId, entityIds) {
184
+ const objectId = toObjectId(integrationId);
185
+ if (!objectId) return null;
186
+ const result = await updateOne(
187
+ this.prisma,
188
+ 'Integration',
189
+ { _id: objectId },
190
+ {
191
+ $pullAll: { entityIds: toObjectIdArray(entityIds) },
192
+ $set: { updatedAt: { $date: new Date().toISOString() } },
193
+ }
194
+ );
195
+ if (!result?.n) return null;
196
+ return this.findIntegrationById(integrationId);
197
+ }
198
+
199
+ async findIntegrationByUserId(userId) {
200
+ const objectId = toObjectId(userId);
201
+ if (!objectId) return null;
202
+ const doc = await findOne(this.prisma, 'Integration', { userId: objectId });
203
+ return doc ? this._mapIntegration(doc) : null;
204
+ }
205
+
206
+ async updateIntegrationConfig(integrationId, config) {
207
+ if (config === null || config === undefined) {
208
+ throw new Error('Config parameter is required');
209
+ }
210
+ const objectId = toObjectId(integrationId);
211
+ if (!objectId) {
212
+ throw new Error(`Integration with id ${integrationId} not found`);
213
+ }
214
+ await updateOne(
215
+ this.prisma,
216
+ 'Integration',
217
+ { _id: objectId },
218
+ {
219
+ $set: {
220
+ config,
221
+ updatedAt: new Date(),
222
+ },
223
+ }
224
+ );
225
+ const updated = await findOne(this.prisma, 'Integration', { _id: objectId });
226
+ if (!updated) {
227
+ console.error('[IntegrationRepositoryDocumentDB] Integration not found after update', {
228
+ integrationId: fromObjectId(objectId),
229
+ config,
230
+ });
231
+ throw new Error(
232
+ 'Failed to update integration: Document not found after update. ' +
233
+ 'This indicates a database consistency issue.'
234
+ );
235
+ }
236
+ return this._mapIntegration(updated);
237
+ }
238
+
239
+ /**
240
+ * Atomically merge a patch into the existing config with a per-key
241
+ * $set (config.<k> for each patch key), then re-read to shape the
242
+ * return value — DocumentDB's raw update command doesn't return the
243
+ * post-update document directly.
244
+ *
245
+ * @param {string} integrationId - Integration ID
246
+ * @param {Object} patch - Keys to merge into the existing config
247
+ * @returns {Promise<Object>} Updated integration object
248
+ */
249
+ async patchIntegrationConfig(integrationId, patch) {
250
+ validateConfigPatch(patch);
251
+ const objectId = toObjectId(integrationId);
252
+ if (!objectId) {
253
+ throw new Error(`Integration with id ${integrationId} not found`);
254
+ }
255
+
256
+ const $set = { updatedAt: new Date() };
257
+ for (const [key, value] of Object.entries(patch)) {
258
+ $set[`config.${key}`] = value;
259
+ }
260
+
261
+ const result = await updateOne(
262
+ this.prisma,
263
+ 'Integration',
264
+ { _id: objectId },
265
+ { $set }
266
+ );
267
+ if (result.writeErrors?.length) {
268
+ throw new Error(
269
+ `Failed to patch integration config: ${result.writeErrors[0].errmsg}`
270
+ );
271
+ }
272
+ if (!result.n) {
273
+ throw new Error(`Integration with id ${integrationId} not found`);
274
+ }
275
+
276
+ const updated = await findOne(this.prisma, 'Integration', { _id: objectId });
277
+ if (!updated) {
278
+ console.error('[IntegrationRepositoryDocumentDB] Integration not found after update', {
279
+ integrationId: fromObjectId(objectId),
280
+ patch,
281
+ });
282
+ throw new Error(
283
+ 'Failed to update integration: Document not found after update. ' +
284
+ 'This indicates a database consistency issue.'
285
+ );
286
+ }
287
+ return this._mapIntegration(updated);
288
+ }
289
+
290
+ // Drain the full cursor so a deployment-wide report is never truncated.
291
+ async findAllForReport({ status, userId } = {}) {
292
+ const filter = {};
293
+ if (status) filter.status = status;
294
+ if (userId !== undefined && userId !== null) {
295
+ const objectId = toObjectId(userId);
296
+ // Invalid userId means no matches — don't fall through to an unfiltered whole-deployment query.
297
+ if (!objectId) return [];
298
+ filter.userId = objectId;
299
+ }
300
+
301
+ const docs = await findManyDrained(this.prisma, 'Integration', filter);
302
+
303
+ return docs.map((doc) => {
304
+ const errors = this._extractReportErrors(doc);
305
+ return {
306
+ id: fromObjectId(doc?._id),
307
+ type: doc?.config?.type ?? null,
308
+ status: doc?.status ?? null,
309
+ userId: fromObjectId(doc?.userId) ?? null,
310
+ version: doc?.version ?? null,
311
+ errorCount: Array.isArray(errors) ? errors.length : 0,
312
+ moduleCount: Array.isArray(doc?.entityIds)
313
+ ? doc.entityIds.length
314
+ : 0,
315
+ createdAt: doc?.createdAt ?? null,
316
+ updatedAt: doc?.updatedAt ?? null,
317
+ };
318
+ });
319
+ }
320
+
321
+ _extractReportErrors(doc) {
322
+ if (Array.isArray(doc?.errors)) return doc.errors;
323
+ if (Array.isArray(doc?.messages?.errors)) return doc.messages.errors;
324
+ return [];
325
+ }
326
+
327
+ _mapIntegration(doc) {
328
+ const messages = this._extractMessages(doc);
329
+ return {
330
+ id: fromObjectId(doc?._id),
331
+ entitiesIds: (doc?.entityIds || []).map((value) => fromObjectId(value)),
332
+ userId: fromObjectId(doc?.userId),
333
+ config: doc?.config ?? null,
334
+ version: doc?.version ?? null,
335
+ status: doc?.status ?? null,
336
+ messages,
337
+ createdAt: doc?.createdAt ?? null,
338
+ };
339
+ }
340
+
341
+ _extractMessages(doc) {
342
+ const base = doc?.messages && typeof doc.messages === 'object' ? doc.messages : {};
343
+ return {
344
+ errors: base.errors ?? doc?.errors ?? [],
345
+ warnings: base.warnings ?? doc?.warnings ?? [],
346
+ info: base.info ?? doc?.info ?? [],
347
+ logs: base.logs ?? doc?.logs ?? [],
348
+ };
349
+ }
350
+ }
351
+
352
+ module.exports = { IntegrationRepositoryDocumentDB };
353
+
354
+
@@ -0,0 +1,51 @@
1
+ const { IntegrationRepositoryMongo } = require('./integration-repository-mongo');
2
+ const { IntegrationRepositoryPostgres } = require('./integration-repository-postgres');
3
+ const {
4
+ IntegrationRepositoryDocumentDB,
5
+ } = require('./integration-repository-documentdb');
6
+ const config = require('../../database/config');
7
+
8
+ /**
9
+ * Integration Repository Factory
10
+ * Creates the appropriate repository adapter based on database type
11
+ *
12
+ * This implements the Factory pattern for Hexagonal Architecture:
13
+ * - Reads database type from app definition (backend/index.js)
14
+ * - Returns correct adapter (MongoDB or PostgreSQL)
15
+ * - Provides clear error for unsupported databases
16
+ *
17
+ * Usage:
18
+ * ```javascript
19
+ * const repository = createIntegrationRepository();
20
+ * ```
21
+ *
22
+ * @returns {IntegrationRepositoryInterface} Configured repository adapter
23
+ * @throws {Error} If database type is not supported
24
+ */
25
+ function createIntegrationRepository() {
26
+ const dbType = config.DB_TYPE;
27
+
28
+ switch (dbType) {
29
+ case 'mongodb':
30
+ return new IntegrationRepositoryMongo();
31
+
32
+ case 'postgresql':
33
+ return new IntegrationRepositoryPostgres();
34
+
35
+ case 'documentdb':
36
+ return new IntegrationRepositoryDocumentDB();
37
+
38
+ default:
39
+ throw new Error(
40
+ `Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
41
+ );
42
+ }
43
+ }
44
+
45
+ module.exports = {
46
+ createIntegrationRepository,
47
+ // Export adapters for direct testing
48
+ IntegrationRepositoryMongo,
49
+ IntegrationRepositoryPostgres,
50
+ IntegrationRepositoryDocumentDB,
51
+ };