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

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 +184 -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 +91 -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,502 @@
1
+ const { prisma } = require('../../database/prisma');
2
+ const {
3
+ IntegrationRepositoryInterface,
4
+ } = require('./integration-repository-interface');
5
+ const { validateConfigPatch } = require('./config-patch-shared');
6
+
7
+ /**
8
+ * MongoDB Integration Repository Adapter
9
+ * Handles integration persistence using Prisma with MongoDB
10
+ *
11
+ * MongoDB-specific characteristics:
12
+ * - Uses scalar fields for relations (userId, entityIds)
13
+ * - IDs are strings with @db.ObjectId
14
+ * - Arrays used for many-to-many relationships
15
+ *
16
+ * Migration from Mongoose:
17
+ * - Constructor injection of Prisma client
18
+ * - populate() → include in Prisma queries
19
+ * - lean: true → No longer needed (Prisma returns plain objects)
20
+ * - toString() conversions → Done automatically by Prisma
21
+ */
22
+ class IntegrationRepositoryMongo extends IntegrationRepositoryInterface {
23
+ constructor() {
24
+ super();
25
+ this.prisma = prisma;
26
+ }
27
+
28
+ /**
29
+ * Find all integrations for a user
30
+ * Replaces: IntegrationModel.find({ user: userId }).populate('entities')
31
+ *
32
+ * @param {string} userId - User ID (MongoDB ObjectId as string)
33
+ * @returns {Promise<Array>} Array of integration objects
34
+ */
35
+ async findIntegrationsByUserId(userId) {
36
+ const integrations = await this.prisma.integration.findMany({
37
+ where: { userId },
38
+ include: {
39
+ entities: true,
40
+ },
41
+ });
42
+
43
+ // Map to domain objects (maintains same API)
44
+ return integrations.map((integration) => ({
45
+ id: integration.id,
46
+ entitiesIds: integration.entities.map((e) => e.id),
47
+ userId: integration.userId,
48
+ config: integration.config,
49
+ version: integration.version,
50
+ status: integration.status,
51
+ messages: integration.messages,
52
+ createdAt: integration.createdAt,
53
+ }));
54
+ }
55
+
56
+ /**
57
+ * Find integrations, optionally filtered by config type and/or status.
58
+ *
59
+ * @param {Object} [filter={}]
60
+ * @param {string} [filter.type] - Integration type (config.type)
61
+ * @param {string} [filter.status] - Integration status
62
+ * @returns {Promise<Array>} Array of integration objects (possibly empty)
63
+ */
64
+ async findIntegrations({ type, status } = {}) {
65
+ const where = {};
66
+ if (type) {
67
+ where.config = { path: ['type'], equals: type };
68
+ }
69
+ if (status) {
70
+ where.status = status;
71
+ }
72
+
73
+ const integrations = await this.prisma.integration.findMany({
74
+ where,
75
+ include: {
76
+ entities: true,
77
+ },
78
+ });
79
+
80
+ return integrations.map((integration) => ({
81
+ id: integration.id,
82
+ entitiesIds: integration.entities.map((e) => e.id),
83
+ userId: integration.userId,
84
+ config: integration.config,
85
+ version: integration.version,
86
+ status: integration.status,
87
+ messages: integration.messages,
88
+ createdAt: integration.createdAt,
89
+ }));
90
+ }
91
+
92
+ /**
93
+ * Find every integration in a report-shaped projection.
94
+ *
95
+ * type lives in config.type (a JSON path not portably groupable across
96
+ * DBs); it is left in the row for the caller to bucket.
97
+ *
98
+ * @param {Object} [filter={}]
99
+ * @param {string} [filter.status] - Integration status
100
+ * @param {string} [filter.userId] - Owning user ID (ObjectId as string)
101
+ * @returns {Promise<Array>} Report-shaped integration rows
102
+ */
103
+ async findAllForReport({ status, userId } = {}) {
104
+ const where = {};
105
+ if (status) where.status = status;
106
+ if (userId !== undefined && userId !== null) where.userId = userId;
107
+
108
+ const integrations = await this.prisma.integration.findMany({
109
+ where,
110
+ include: { entities: { select: { id: true } } },
111
+ });
112
+
113
+ return integrations.map((integration) => ({
114
+ id: integration.id,
115
+ type: integration.config?.type ?? null,
116
+ status: integration.status ?? null,
117
+ userId: integration.userId ?? null,
118
+ version: integration.version ?? null,
119
+ errorCount: Array.isArray(integration.errors)
120
+ ? integration.errors.length
121
+ : 0,
122
+ moduleCount: integration.entities?.length ?? 0,
123
+ createdAt: integration.createdAt ?? null,
124
+ updatedAt: integration.updatedAt ?? null,
125
+ }));
126
+ }
127
+
128
+ /**
129
+ * Delete integration by ID
130
+ * Replaces: IntegrationModel.deleteOne({ _id: integrationId })
131
+ *
132
+ * @param {string} integrationId - Integration ID
133
+ * @returns {Promise<Object>} Deletion result
134
+ */
135
+ async deleteIntegrationById(integrationId) {
136
+ await this.prisma.integration.delete({
137
+ where: { id: integrationId },
138
+ });
139
+
140
+ // Return Mongoose-compatible result
141
+ return { acknowledged: true, deletedCount: 1 };
142
+ }
143
+
144
+ /**
145
+ * Find integration by name
146
+ * Replaces: IntegrationModel.findOne({ 'config.type': name }).populate('entities')
147
+ *
148
+ * @param {string} name - Integration type name
149
+ * @returns {Promise<Object>} Integration object
150
+ */
151
+ async findIntegrationByName(name) {
152
+ const integration = await this.prisma.integration.findFirst({
153
+ where: {
154
+ config: {
155
+ path: ['type'],
156
+ equals: name,
157
+ },
158
+ },
159
+ include: {
160
+ entities: true,
161
+ },
162
+ });
163
+
164
+ if (!integration) {
165
+ throw new Error(`Integration with name ${name} not found`);
166
+ }
167
+
168
+ return {
169
+ id: integration.id,
170
+ entitiesIds: integration.entities.map((e) => e.id),
171
+ userId: integration.userId,
172
+ config: integration.config,
173
+ version: integration.version,
174
+ status: integration.status,
175
+ messages: integration.messages,
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Find integration by ID
181
+ * Replaces: IntegrationModel.findById(id).populate('entities')
182
+ *
183
+ * @param {string} id - Integration ID
184
+ * @returns {Promise<Object>} Integration object
185
+ */
186
+ async findIntegrationById(id) {
187
+ const integration = await this.prisma.integration.findUnique({
188
+ where: { id },
189
+ include: {
190
+ entities: true,
191
+ },
192
+ });
193
+
194
+ if (!integration) {
195
+ throw new Error(`Integration with id ${id} not found`);
196
+ }
197
+
198
+ return {
199
+ id: integration.id,
200
+ entitiesIds: integration.entities.map((e) => e.id),
201
+ userId: integration.userId,
202
+ config: integration.config,
203
+ version: integration.version,
204
+ status: integration.status,
205
+ messages: integration.messages,
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Update integration status
211
+ * Replaces: IntegrationModel.updateOne({ _id: integrationId }, { status })
212
+ *
213
+ * @param {string} integrationId - Integration ID
214
+ * @param {string} status - New status
215
+ * @returns {Promise<boolean>} Success indicator
216
+ */
217
+ async updateIntegrationStatus(integrationId, status) {
218
+ await this.prisma.integration.update({
219
+ where: { id: integrationId },
220
+ data: { status },
221
+ });
222
+
223
+ return true; // Mongoose compatibility
224
+ }
225
+
226
+ /**
227
+ * Update integration messages
228
+ * Replaces: IntegrationModel.updateOne with $push operator
229
+ *
230
+ * @param {string} integrationId - Integration ID
231
+ * @param {string} messageType - Type of message (errors, warnings, info, logs)
232
+ * @param {string} messageTitle - Message title
233
+ * @param {string} messageBody - Message body
234
+ * @param {Date} messageTimestamp - Message timestamp
235
+ * @returns {Promise<boolean>} Success indicator
236
+ */
237
+ async updateIntegrationMessages(
238
+ integrationId,
239
+ messageType,
240
+ messageTitle,
241
+ messageBody,
242
+ messageTimestamp
243
+ ) {
244
+ // Get current integration
245
+ const integration = await this.prisma.integration.findUnique({
246
+ where: { id: integrationId },
247
+ });
248
+
249
+ if (!integration) {
250
+ throw new Error(`Integration ${integrationId} not found`);
251
+ }
252
+
253
+ // Parse existing messages (JSON field)
254
+ const messages = integration.messages || {};
255
+ const messageArray = Array.isArray(messages[messageType])
256
+ ? messages[messageType]
257
+ : [];
258
+
259
+ // Add new message
260
+ messageArray.push({
261
+ title: messageTitle,
262
+ message: messageBody,
263
+ timestamp: messageTimestamp,
264
+ });
265
+
266
+ // Update messages
267
+ await this.prisma.integration.update({
268
+ where: { id: integrationId },
269
+ data: {
270
+ [messageType]: messageArray,
271
+ },
272
+ });
273
+
274
+ return true; // Mongoose compatibility
275
+ }
276
+
277
+ /**
278
+ * Find all integrations whose entity set includes the given entity ID.
279
+ *
280
+ * @param {string} entityId - Entity ID (MongoDB ObjectId as string)
281
+ * @returns {Promise<Array>} Array of integration objects (possibly empty)
282
+ */
283
+ async findIntegrationsByEntityId(entityId) {
284
+ const integrations = await this.prisma.integration.findMany({
285
+ where: {
286
+ entityIds: { has: entityId },
287
+ },
288
+ include: {
289
+ entities: true,
290
+ },
291
+ });
292
+
293
+ return integrations.map((integration) => ({
294
+ id: integration.id,
295
+ entitiesIds: integration.entities.map((e) => e.id),
296
+ userId: integration.userId,
297
+ config: integration.config,
298
+ version: integration.version,
299
+ status: integration.status,
300
+ messages: integration.messages,
301
+ }));
302
+ }
303
+
304
+ /**
305
+ * Create a new integration
306
+ * Replaces: IntegrationModel.create({ entities, user, config })
307
+ *
308
+ * MongoDB-specific: Uses scalar fields for relations
309
+ *
310
+ * @param {Array<string>} entities - Array of entity IDs (MongoDB ObjectIds)
311
+ * @param {string} userId - User ID (MongoDB ObjectId)
312
+ * @param {Object} config - Integration configuration
313
+ * @returns {Promise<Object>} Created integration object
314
+ */
315
+ async createIntegration(entities, userId, config) {
316
+ const data = {
317
+ config,
318
+ version: '0.0.0',
319
+ userId: userId,
320
+ entityIds: entities,
321
+ };
322
+
323
+ const integration = await this.prisma.integration.create({
324
+ data,
325
+ include: {
326
+ entities: true,
327
+ },
328
+ });
329
+
330
+ return {
331
+ id: integration.id,
332
+ entitiesIds: integration.entities.map((e) => e.id),
333
+ userId: integration.userId,
334
+ config: integration.config,
335
+ version: integration.version,
336
+ status: integration.status,
337
+ messages: integration.messages,
338
+ };
339
+ }
340
+
341
+ /**
342
+ * Attach entities to an existing integration. Entities already attached
343
+ * are left as they are.
344
+ *
345
+ * @param {string} integrationId - Integration ID
346
+ * @param {Array<string>} entityIds - Entity IDs to attach
347
+ * @returns {Promise<Object|null>} Updated integration, or null when the integration does not exist
348
+ */
349
+ async addEntitiesToIntegration(integrationId, entityIds) {
350
+
351
+ try {
352
+ await this.prisma.integration.update({
353
+ where: { id: integrationId },
354
+ data: {
355
+ entities: {
356
+ connect: entityIds.map((id) => ({ id })),
357
+ },
358
+ },
359
+ });
360
+ } catch (error) {
361
+ if (error.code === 'P2025') return null;
362
+ throw error;
363
+ }
364
+ return this.findIntegrationById(integrationId);
365
+ }
366
+
367
+ /**
368
+ * Detach entities from an integration. Entities that are not attached
369
+ * are ignored. The entities themselves are not deleted.
370
+ *
371
+ * @param {string} integrationId - Integration ID
372
+ * @param {Array<string>} entityIds - Entity IDs to detach
373
+ * @returns {Promise<Object|null>} Updated integration, or null when the integration does not exist
374
+ */
375
+ async removeEntitiesFromIntegration(integrationId, entityIds) {
376
+
377
+ try {
378
+ await this.prisma.integration.update({
379
+ where: { id: integrationId },
380
+ data: {
381
+ entities: {
382
+ disconnect: entityIds.map((id) => ({ id })),
383
+ },
384
+ },
385
+ });
386
+ } catch (error) {
387
+ if (error.code === 'P2025') return null;
388
+ throw error;
389
+ }
390
+ return this.findIntegrationById(integrationId);
391
+ }
392
+
393
+ /**
394
+ * Find integration by user ID (returns single integration)
395
+ * Replaces: IntegrationModel.findOne({ user: userId }).populate('entities')
396
+ *
397
+ * @param {string} userId - User ID
398
+ * @returns {Promise<Object|null>} Integration object or null
399
+ */
400
+ async findIntegrationByUserId(userId) {
401
+ const integration = await this.prisma.integration.findFirst({
402
+ where: { userId },
403
+ include: {
404
+ entities: true,
405
+ },
406
+ });
407
+
408
+ if (!integration) {
409
+ return null;
410
+ }
411
+
412
+ return {
413
+ id: integration.id,
414
+ entitiesIds: integration.entities.map((e) => e.id),
415
+ userId: integration.userId,
416
+ config: integration.config,
417
+ version: integration.version,
418
+ status: integration.status,
419
+ messages: integration.messages,
420
+ };
421
+ }
422
+
423
+ /**
424
+ * Update integration configuration
425
+ * Replaces: IntegrationModel.updateOne({ _id: integrationId }, { config })
426
+ *
427
+ * @param {string} integrationId - Integration ID (MongoDB ObjectId as string)
428
+ * @param {Object} config - Updated configuration object
429
+ * @returns {Promise<Object>} Updated integration object
430
+ */
431
+ async updateIntegrationConfig(integrationId, config) {
432
+ if (config === null || config === undefined) {
433
+ throw new Error('Config parameter is required');
434
+ }
435
+
436
+ const integration = await this.prisma.integration.update({
437
+ where: { id: integrationId },
438
+ data: { config },
439
+ include: {
440
+ entities: true,
441
+ },
442
+ });
443
+
444
+ return {
445
+ id: integration.id,
446
+ entitiesIds: integration.entities.map((e) => e.id),
447
+ userId: integration.userId,
448
+ config: integration.config,
449
+ version: integration.version,
450
+ status: integration.status,
451
+ messages: integration.messages,
452
+ };
453
+ }
454
+
455
+ /**
456
+ * Atomically merge a patch into the existing config via findAndModify,
457
+ * so the write and the post-write read happen in one server-side round
458
+ * trip with no JS-side read-modify-write to race on. entityIds is a
459
+ * scalar array directly on the Integration document in Mongo, so the
460
+ * raw document already carries everything needed to shape the return
461
+ * value — no follow-up findUnique.
462
+ *
463
+ * @param {string} integrationId - Integration ID
464
+ * @param {Object} patch - Keys to merge into the existing config
465
+ * @returns {Promise<Object>} Updated integration object
466
+ */
467
+ async patchIntegrationConfig(integrationId, patch) {
468
+ validateConfigPatch(patch);
469
+
470
+ const $set = {};
471
+ for (const [key, value] of Object.entries(patch)) {
472
+ $set[`config.${key}`] = value;
473
+ }
474
+ $set.updatedAt = { $date: new Date().toISOString() };
475
+
476
+ const result = await this.prisma.$runCommandRaw({
477
+ findAndModify: 'Integration',
478
+ query: { _id: { $oid: integrationId } },
479
+ update: { $set },
480
+ new: true,
481
+ });
482
+
483
+ const doc = result && result.value;
484
+ if (!doc) {
485
+ throw new Error(`Integration with id ${integrationId} not found`);
486
+ }
487
+
488
+ return {
489
+ id: doc._id.$oid ?? doc._id,
490
+ entitiesIds: (doc.entityIds || []).map(
491
+ (entityId) => entityId.$oid ?? entityId
492
+ ),
493
+ userId: doc.userId?.$oid ?? doc.userId ?? null,
494
+ config: doc.config,
495
+ version: doc.version,
496
+ status: doc.status,
497
+ messages: doc.messages,
498
+ };
499
+ }
500
+ }
501
+
502
+ module.exports = { IntegrationRepositoryMongo };