@friggframework/core 2.0.0-next.11 → 2.0.0-next.110

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 (375) hide show
  1. package/CLAUDE.md +702 -0
  2. package/README.md +999 -50
  3. package/admin-scripts/index.js +52 -0
  4. package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
  5. package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
  6. package/admin-scripts/repositories/admin-script-execution-repository-interface.js +171 -0
  7. package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +238 -0
  8. package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +278 -0
  9. package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
  10. package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
  11. package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
  12. package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
  13. package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
  14. package/application/commands/README.md +451 -0
  15. package/application/commands/admin-script-commands.js +359 -0
  16. package/application/commands/credential-commands.js +262 -0
  17. package/application/commands/entity-commands.js +336 -0
  18. package/application/commands/integration-commands.js +356 -0
  19. package/application/commands/integration-mapping-commands.js +25 -0
  20. package/application/commands/process-commands.js +135 -0
  21. package/application/commands/report-commands.js +188 -0
  22. package/application/commands/scheduler-commands.js +263 -0
  23. package/application/commands/usage-commands.js +56 -0
  24. package/application/commands/user-commands.js +312 -0
  25. package/application/index.js +83 -0
  26. package/artifacts/repositories/artifact-repository-factory.js +19 -0
  27. package/artifacts/repositories/artifact-repository-interface.js +27 -0
  28. package/artifacts/repositories/artifact-repository-local.js +42 -0
  29. package/artifacts/repositories/artifact-repository-s3.js +61 -0
  30. package/assertions/index.js +0 -3
  31. package/core/CLAUDE.md +700 -0
  32. package/core/Worker.js +60 -24
  33. package/core/create-handler.js +189 -5
  34. package/core/parameters-to-env.js +257 -0
  35. package/core/ssm-preload.mjs +34 -0
  36. package/credential/repositories/credential-active-type.js +32 -0
  37. package/credential/repositories/credential-repository-documentdb.js +355 -0
  38. package/credential/repositories/credential-repository-factory.js +54 -0
  39. package/credential/repositories/credential-repository-interface.js +113 -0
  40. package/credential/repositories/credential-repository-mongo.js +294 -0
  41. package/credential/repositories/credential-repository-postgres.js +312 -0
  42. package/credential/repositories/credential-repository.js +300 -0
  43. package/credential/use-cases/get-credential-for-user.js +25 -0
  44. package/credential/use-cases/update-authentication-status.js +15 -0
  45. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  46. package/database/adapters/lambda-invoker.js +97 -0
  47. package/database/config.js +154 -0
  48. package/database/documentdb-encryption-service.js +330 -0
  49. package/database/documentdb-utils.js +192 -0
  50. package/database/encryption/README.md +839 -0
  51. package/database/encryption/documentdb-encryption-service.md +3575 -0
  52. package/database/encryption/encryption-schema-registry.js +401 -0
  53. package/database/encryption/field-encryption-service.js +254 -0
  54. package/database/encryption/logger.js +79 -0
  55. package/database/encryption/prisma-encryption-extension.js +230 -0
  56. package/database/index.js +21 -21
  57. package/database/prisma.js +182 -0
  58. package/database/repositories/health-check-repository-documentdb.js +138 -0
  59. package/database/repositories/health-check-repository-factory.js +48 -0
  60. package/database/repositories/health-check-repository-interface.js +82 -0
  61. package/database/repositories/health-check-repository-mongodb.js +89 -0
  62. package/database/repositories/health-check-repository-postgres.js +82 -0
  63. package/database/repositories/migration-status-repository-s3.js +137 -0
  64. package/database/use-cases/check-database-health-use-case.js +29 -0
  65. package/database/use-cases/check-database-state-use-case.js +81 -0
  66. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  67. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  68. package/database/use-cases/get-migration-status-use-case.js +93 -0
  69. package/database/use-cases/resolve-migration-via-worker-use-case.js +49 -0
  70. package/database/use-cases/run-database-migration-use-case.js +139 -0
  71. package/database/use-cases/test-encryption-use-case.js +253 -0
  72. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  73. package/database/utils/mongodb-collection-utils.js +94 -0
  74. package/database/utils/mongodb-schema-init.js +108 -0
  75. package/database/utils/prisma-runner.js +491 -0
  76. package/database/utils/prisma-schema-parser.js +182 -0
  77. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  78. package/encrypt/Cryptor.js +34 -168
  79. package/encrypt/index.js +1 -2
  80. package/errors/client-safe-error.js +26 -0
  81. package/errors/fetch-error.js +15 -7
  82. package/errors/index.js +2 -0
  83. package/generated/prisma-mongodb/client.d.ts +1 -0
  84. package/generated/prisma-mongodb/client.js +5 -0
  85. package/generated/prisma-mongodb/default.d.ts +1 -0
  86. package/generated/prisma-mongodb/default.js +5 -0
  87. package/generated/prisma-mongodb/edge.d.ts +1 -0
  88. package/generated/prisma-mongodb/edge.js +386 -0
  89. package/generated/prisma-mongodb/index-browser.js +368 -0
  90. package/generated/prisma-mongodb/index.d.ts +27065 -0
  91. package/generated/prisma-mongodb/index.js +411 -0
  92. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  93. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  94. package/generated/prisma-mongodb/package.json +183 -0
  95. package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
  96. package/generated/prisma-mongodb/runtime/edge.js +35 -0
  97. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  98. package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
  99. package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
  100. package/generated/prisma-mongodb/runtime/library.js +147 -0
  101. package/generated/prisma-mongodb/runtime/react-native.js +84 -0
  102. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
  103. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
  104. package/generated/prisma-mongodb/schema.prisma +455 -0
  105. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
  106. package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
  107. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  108. package/generated/prisma-mongodb/wasm.js +393 -0
  109. package/generated/prisma-postgresql/client.d.ts +1 -0
  110. package/generated/prisma-postgresql/client.js +5 -0
  111. package/generated/prisma-postgresql/default.d.ts +1 -0
  112. package/generated/prisma-postgresql/default.js +5 -0
  113. package/generated/prisma-postgresql/edge.d.ts +1 -0
  114. package/generated/prisma-postgresql/edge.js +407 -0
  115. package/generated/prisma-postgresql/index-browser.js +389 -0
  116. package/generated/prisma-postgresql/index.d.ts +29904 -0
  117. package/generated/prisma-postgresql/index.js +432 -0
  118. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  119. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  120. package/generated/prisma-postgresql/package.json +183 -0
  121. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  122. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  123. package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
  124. package/generated/prisma-postgresql/runtime/edge.js +35 -0
  125. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  126. package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
  127. package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
  128. package/generated/prisma-postgresql/runtime/library.js +147 -0
  129. package/generated/prisma-postgresql/runtime/react-native.js +84 -0
  130. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
  131. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
  132. package/generated/prisma-postgresql/schema.prisma +436 -0
  133. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
  134. package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
  135. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  136. package/generated/prisma-postgresql/wasm.js +414 -0
  137. package/handlers/WEBHOOKS.md +653 -0
  138. package/handlers/app-definition-loader.js +67 -0
  139. package/handlers/app-handler-helpers.js +3 -3
  140. package/handlers/backend-utils.js +271 -42
  141. package/handlers/database-migration-handler.js +227 -0
  142. package/handlers/integration-event-dispatcher.js +68 -0
  143. package/handlers/middleware/admin-auth.js +73 -0
  144. package/handlers/routers/HEALTHCHECK.md +342 -0
  145. package/handlers/routers/auth.js +4 -15
  146. package/handlers/routers/db-migration.handler.js +29 -0
  147. package/handlers/routers/db-migration.js +329 -0
  148. package/handlers/routers/health.js +518 -0
  149. package/handlers/routers/integration-defined-routers.js +85 -10
  150. package/handlers/routers/integration-webhook-routers.js +80 -0
  151. package/handlers/routers/user.js +27 -5
  152. package/handlers/routers/websocket.js +5 -3
  153. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  154. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  155. package/handlers/workers/db-migration.js +427 -0
  156. package/handlers/workers/dlq-processor.js +63 -0
  157. package/handlers/workers/integration-defined-workers.js +13 -7
  158. package/index.js +102 -46
  159. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
  160. package/infrastructure/scheduler/index.js +33 -0
  161. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  162. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  163. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  164. package/integrations/EXTENSIONS.md +240 -0
  165. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  166. package/integrations/extension.js +254 -0
  167. package/integrations/index.js +20 -10
  168. package/integrations/integration-base.js +730 -74
  169. package/integrations/integration-router.js +398 -180
  170. package/integrations/options.js +1 -1
  171. package/integrations/repositories/config-patch-shared.js +43 -0
  172. package/integrations/repositories/integration-mapping-repository-documentdb.js +303 -0
  173. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  174. package/integrations/repositories/integration-mapping-repository-interface.js +120 -0
  175. package/integrations/repositories/integration-mapping-repository-mongo.js +183 -0
  176. package/integrations/repositories/integration-mapping-repository-postgres.js +255 -0
  177. package/integrations/repositories/integration-mapping-repository.js +156 -0
  178. package/integrations/repositories/integration-repository-documentdb.js +322 -0
  179. package/integrations/repositories/integration-repository-factory.js +51 -0
  180. package/integrations/repositories/integration-repository-interface.js +189 -0
  181. package/integrations/repositories/integration-repository-mongo.js +450 -0
  182. package/integrations/repositories/integration-repository-postgres.js +492 -0
  183. package/integrations/repositories/process-repository-documentdb.js +311 -0
  184. package/integrations/repositories/process-repository-factory.js +53 -0
  185. package/integrations/repositories/process-repository-interface.js +136 -0
  186. package/integrations/repositories/process-repository-mongo.js +262 -0
  187. package/integrations/repositories/process-repository-postgres.js +380 -0
  188. package/integrations/repositories/process-update-ops-shared.js +112 -0
  189. package/integrations/repositories/report-id.js +13 -0
  190. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  191. package/integrations/tests/doubles/dummy-integration-class.js +113 -0
  192. package/integrations/tests/doubles/test-integration-repository.js +146 -0
  193. package/integrations/use-cases/create-integration.js +215 -0
  194. package/integrations/use-cases/create-process.js +130 -0
  195. package/integrations/use-cases/delete-integration-for-user.js +119 -0
  196. package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
  197. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
  198. package/integrations/use-cases/get-integration-for-user.js +78 -0
  199. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  200. package/integrations/use-cases/get-integration-instance.js +83 -0
  201. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  202. package/integrations/use-cases/get-possible-integrations.js +27 -0
  203. package/integrations/use-cases/get-process.js +89 -0
  204. package/integrations/use-cases/index.js +19 -0
  205. package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
  206. package/integrations/use-cases/load-integration-context.js +71 -0
  207. package/integrations/use-cases/patch-integration-config.js +39 -0
  208. package/integrations/use-cases/process-errors.js +28 -0
  209. package/integrations/use-cases/update-integration-config.js +32 -0
  210. package/integrations/use-cases/update-integration-messages.js +44 -0
  211. package/integrations/use-cases/update-integration-status.js +32 -0
  212. package/integrations/use-cases/update-integration.js +92 -0
  213. package/integrations/use-cases/update-process-metrics.js +222 -0
  214. package/integrations/use-cases/update-process-state.js +163 -0
  215. package/integrations/utils/map-integration-dto.js +37 -0
  216. package/jest-global-setup-noop.js +3 -0
  217. package/jest-global-teardown-noop.js +3 -0
  218. package/logs/logger.js +0 -4
  219. package/{module-plugin → modules}/index.js +0 -10
  220. package/modules/module-factory.js +56 -0
  221. package/modules/module.js +307 -0
  222. package/modules/repositories/module-repository-documentdb.js +350 -0
  223. package/modules/repositories/module-repository-factory.js +40 -0
  224. package/modules/repositories/module-repository-interface.js +145 -0
  225. package/modules/repositories/module-repository-mongo.js +436 -0
  226. package/modules/repositories/module-repository-postgres.js +481 -0
  227. package/modules/repositories/module-repository.js +369 -0
  228. package/modules/requester/api-key.js +52 -0
  229. package/modules/requester/oauth-2.js +555 -0
  230. package/modules/requester/requester.js +542 -0
  231. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  232. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  233. package/modules/tests/doubles/test-module-factory.js +16 -0
  234. package/modules/tests/doubles/test-module-repository.js +39 -0
  235. package/modules/use-cases/get-entities-for-user.js +32 -0
  236. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  237. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  238. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  239. package/modules/use-cases/get-module.js +74 -0
  240. package/modules/use-cases/process-authorization-callback.js +243 -0
  241. package/modules/use-cases/refresh-entity-options.js +72 -0
  242. package/modules/use-cases/test-module-auth.js +72 -0
  243. package/modules/utils/map-module-dto.js +18 -0
  244. package/package.json +92 -50
  245. package/prisma-mongodb/schema.prisma +455 -0
  246. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  247. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  248. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  249. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  250. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  251. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  252. package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
  253. package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
  254. package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
  255. package/prisma-postgresql/migrations/20260705000000_create_usage_counter/migration.sql +26 -0
  256. package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
  257. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  258. package/prisma-postgresql/schema.prisma +436 -0
  259. package/queues/queuer-util.js +103 -21
  260. package/reporting/README.md +154 -0
  261. package/reporting/builtin-reports.js +6 -0
  262. package/reporting/index.js +13 -0
  263. package/reporting/report-base.js +49 -0
  264. package/reporting/reports/integrations-report.js +221 -0
  265. package/syncs/manager.js +468 -443
  266. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  267. package/syncs/repositories/sync-repository-factory.js +43 -0
  268. package/syncs/repositories/sync-repository-interface.js +109 -0
  269. package/syncs/repositories/sync-repository-mongo.js +239 -0
  270. package/syncs/repositories/sync-repository-postgres.js +319 -0
  271. package/syncs/sync.js +0 -1
  272. package/telemetry/README.md +331 -0
  273. package/telemetry/bind-telemetry-context.js +73 -0
  274. package/telemetry/canonical-counters.js +52 -0
  275. package/telemetry/exporters.js +85 -0
  276. package/telemetry/index.js +26 -0
  277. package/telemetry/instrument-handler.js +87 -0
  278. package/telemetry/no-op-telemetry.js +67 -0
  279. package/telemetry/north-star.js +103 -0
  280. package/telemetry/otel-telemetry.js +213 -0
  281. package/telemetry/plugin-subscribers.js +77 -0
  282. package/telemetry/telemetry-config.js +120 -0
  283. package/telemetry/telemetry-context.js +40 -0
  284. package/telemetry/telemetry-event-bus.js +58 -0
  285. package/telemetry/telemetry-runtime.js +147 -0
  286. package/telemetry/telemetry-service.js +51 -0
  287. package/telemetry/usage-rollup-subscriber.js +116 -0
  288. package/token/repositories/token-repository-documentdb.js +137 -0
  289. package/token/repositories/token-repository-factory.js +40 -0
  290. package/token/repositories/token-repository-interface.js +131 -0
  291. package/token/repositories/token-repository-mongo.js +219 -0
  292. package/token/repositories/token-repository-postgres.js +264 -0
  293. package/token/repositories/token-repository.js +219 -0
  294. package/types/associations/index.d.ts +0 -17
  295. package/types/core/index.d.ts +12 -4
  296. package/types/database/index.d.ts +10 -2
  297. package/types/encrypt/index.d.ts +5 -3
  298. package/types/integrations/index.d.ts +3 -8
  299. package/types/module-plugin/index.d.ts +20 -69
  300. package/types/syncs/index.d.ts +0 -17
  301. package/usage/README.md +54 -0
  302. package/usage/index.js +17 -0
  303. package/usage/repositories/usage-repository-documentdb.js +194 -0
  304. package/usage/repositories/usage-repository-factory.js +25 -0
  305. package/usage/repositories/usage-repository-interface.js +37 -0
  306. package/usage/repositories/usage-repository-prisma.js +146 -0
  307. package/usage/tracked-metrics.js +38 -0
  308. package/usage/usage-windows.js +24 -0
  309. package/user/repositories/user-repository-documentdb.js +458 -0
  310. package/user/repositories/user-repository-factory.js +52 -0
  311. package/user/repositories/user-repository-interface.js +214 -0
  312. package/user/repositories/user-repository-mongo.js +323 -0
  313. package/user/repositories/user-repository-postgres.js +377 -0
  314. package/user/tests/doubles/test-user-repository.js +72 -0
  315. package/user/use-cases/authenticate-user.js +127 -0
  316. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  317. package/user/use-cases/create-individual-user.js +61 -0
  318. package/user/use-cases/create-organization-user.js +47 -0
  319. package/user/use-cases/create-token-for-user-id.js +30 -0
  320. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  321. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  322. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  323. package/user/use-cases/login-user.js +122 -0
  324. package/user/user.js +125 -0
  325. package/utils/backend-path.js +38 -0
  326. package/utils/index.js +6 -0
  327. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  328. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  329. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  330. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  331. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  332. package/websocket/repositories/websocket-connection-repository.js +161 -0
  333. package/assertions/is-equal.js +0 -17
  334. package/associations/model.js +0 -54
  335. package/database/models/IndividualUser.js +0 -76
  336. package/database/models/OrganizationUser.js +0 -29
  337. package/database/models/State.js +0 -9
  338. package/database/models/Token.js +0 -70
  339. package/database/models/UserModel.js +0 -7
  340. package/database/models/WebsocketConnection.js +0 -49
  341. package/database/mongo.js +0 -45
  342. package/database/mongoose.js +0 -5
  343. package/encrypt/Cryptor.test.js +0 -32
  344. package/encrypt/encrypt.js +0 -132
  345. package/encrypt/encrypt.test.js +0 -1069
  346. package/encrypt/test-encrypt.js +0 -107
  347. package/errors/base-error.test.js +0 -32
  348. package/errors/fetch-error.test.js +0 -79
  349. package/errors/halt-error.test.js +0 -11
  350. package/errors/validation-errors.test.js +0 -120
  351. package/handlers/routers/middleware/loadUser.js +0 -15
  352. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  353. package/integrations/create-frigg-backend.js +0 -31
  354. package/integrations/integration-factory.js +0 -251
  355. package/integrations/integration-mapping.js +0 -43
  356. package/integrations/integration-model.js +0 -46
  357. package/integrations/integration-user.js +0 -144
  358. package/integrations/test/integration-base.test.js +0 -144
  359. package/lambda/TimeoutCatcher.test.js +0 -68
  360. package/logs/logger.test.js +0 -76
  361. package/module-plugin/auther.js +0 -393
  362. package/module-plugin/credential.js +0 -22
  363. package/module-plugin/entity-manager.js +0 -70
  364. package/module-plugin/entity.js +0 -46
  365. package/module-plugin/manager.js +0 -169
  366. package/module-plugin/module-factory.js +0 -61
  367. package/module-plugin/requester/api-key.js +0 -36
  368. package/module-plugin/requester/oauth-2.js +0 -219
  369. package/module-plugin/requester/requester.js +0 -165
  370. package/module-plugin/requester/requester.test.js +0 -28
  371. package/module-plugin/test/auther.test.js +0 -97
  372. package/syncs/model.js +0 -62
  373. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  374. /package/{module-plugin → modules}/requester/basic.js +0 -0
  375. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,359 @@
1
+ const ERROR_CODE_MAP = {
2
+ SCRIPT_NOT_FOUND: 404,
3
+ EXECUTION_NOT_FOUND: 404,
4
+ };
5
+
6
+ function mapErrorToResponse(error) {
7
+ const status = ERROR_CODE_MAP[error?.code] || 500;
8
+ return { error: status, reason: error?.message, code: error?.code };
9
+ }
10
+
11
+ /**
12
+ * Create admin script commands
13
+ * Provides command pattern API for admin script management
14
+ *
15
+ * This follows the Command pattern from integration-commands.js:
16
+ * - Creates repositories via factory functions
17
+ * - Maps errors to HTTP-friendly responses
18
+ * - Returns data or error objects (never throws)
19
+ *
20
+ * WHY SEPARATE FROM integration-commands.js:
21
+ * These commands are intentionally separate because they serve different domains:
22
+ * - integration-commands: User-context operations on integrations
23
+ * - Requires integrationClass constructor parameter
24
+ * - Works with userId, entityIds, integration contexts
25
+ * - Uses IntegrationRepository, ModuleRepository
26
+ * - admin-script-commands: System/admin operations without user context
27
+ * - No user context required
28
+ * - Works with AdminScriptExecution, ScriptSchedule
29
+ * - Uses AdminScriptExecutionRepository, ScriptScheduleRepository
30
+ *
31
+ * Merging them would violate SRP and create coupling between
32
+ * user-facing integration code and admin/system code.
33
+ *
34
+ * Authentication:
35
+ * - Uses ENV-based ADMIN_API_KEY (see handlers/middleware/admin-auth.js)
36
+ * - No database-backed API keys (simplified from original design)
37
+ *
38
+ * @returns {Object} Command methods for admin scripts
39
+ */
40
+ function createAdminScriptCommands() {
41
+ // Lazy-load repository factories to avoid circular dependencies
42
+ const {
43
+ createAdminScriptExecutionRepository,
44
+ } = require('../../admin-scripts/repositories/admin-script-execution-repository-factory');
45
+ const {
46
+ createScriptScheduleRepository,
47
+ } = require('../../admin-scripts/repositories/script-schedule-repository-factory');
48
+
49
+ const adminScriptExecutionRepository = createAdminScriptExecutionRepository();
50
+ const scheduleRepository = createScriptScheduleRepository();
51
+
52
+ return {
53
+ // ==================== Admin Script Execution Management Commands ====================
54
+
55
+ /**
56
+ * Create a new admin script execution record
57
+ *
58
+ * @param {Object} params - Execution creation parameters
59
+ * @param {string} params.scriptName - Name of script being executed
60
+ * @param {string} [params.scriptVersion] - Script version
61
+ * @param {string} params.trigger - Trigger type ('MANUAL', 'SCHEDULED', 'QUEUE', 'WEBHOOK')
62
+ * @param {string} [params.mode] - Execution mode ('sync' or 'async', default 'async')
63
+ * @param {Object} [params.input] - Input parameters
64
+ * @param {Object} [params.audit] - Audit information (apiKeyName, apiKeyLast4, ipAddress)
65
+ * @returns {Promise<Object>} Created admin script execution record
66
+ */
67
+ async createExecution({
68
+ scriptName,
69
+ scriptVersion,
70
+ trigger,
71
+ mode,
72
+ input,
73
+ audit,
74
+ parentExecutionId,
75
+ }) {
76
+ try {
77
+ const process = await adminScriptExecutionRepository.createExecution({
78
+ name: scriptName,
79
+ type: 'ADMIN_SCRIPT',
80
+ // Persisted to the parentExecutionId column (self-FK), not the
81
+ // context blob, so the parent/child hierarchy is queryable.
82
+ parentExecutionId,
83
+ context: {
84
+ scriptVersion,
85
+ trigger,
86
+ mode: mode || 'async',
87
+ input,
88
+ audit,
89
+ },
90
+ });
91
+ return process;
92
+ } catch (error) {
93
+ return mapErrorToResponse(error);
94
+ }
95
+ },
96
+
97
+ /**
98
+ * Find an admin script execution by ID
99
+ *
100
+ * @param {string|number} processId - The admin script execution ID
101
+ * @returns {Promise<Object>} Admin script execution record or error
102
+ */
103
+ async findExecutionById(processId) {
104
+ try {
105
+ const process = await adminScriptExecutionRepository.findExecutionById(
106
+ processId
107
+ );
108
+ // Scripts and reports share one store; exclude REPORT rows so the two never read each other's executions.
109
+ if (!process || process.type === 'REPORT') {
110
+ const error = new Error(`Execution ${processId} not found`);
111
+ error.code = 'EXECUTION_NOT_FOUND';
112
+ return mapErrorToResponse(error);
113
+ }
114
+ return process;
115
+ } catch (error) {
116
+ return mapErrorToResponse(error);
117
+ }
118
+ },
119
+
120
+ /**
121
+ * Find all admin script executions for a specific script
122
+ *
123
+ * @param {string} scriptName - Script name to filter by
124
+ * @param {Object} [options] - Query options (limit, offset, sortBy, sortOrder)
125
+ * @returns {Promise<Array>} Array of admin script execution records
126
+ */
127
+ async findExecutionsByName(scriptName, options = {}) {
128
+ try {
129
+ const processes =
130
+ await adminScriptExecutionRepository.findExecutionsByName(
131
+ scriptName,
132
+ options
133
+ );
134
+ return processes;
135
+ } catch (error) {
136
+ // Return empty array on error (non-critical)
137
+ return [];
138
+ }
139
+ },
140
+
141
+ /**
142
+ * Update admin script execution state
143
+ *
144
+ * @param {string|number} processId - The admin script execution ID
145
+ * @param {string} state - New state ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
146
+ * @returns {Promise<Object>} Updated admin script execution record
147
+ */
148
+ async updateExecutionState(processId, state) {
149
+ try {
150
+ const updated = await adminScriptExecutionRepository.updateExecutionState(
151
+ processId,
152
+ state
153
+ );
154
+ return updated;
155
+ } catch (error) {
156
+ return mapErrorToResponse(error);
157
+ }
158
+ },
159
+
160
+ /**
161
+ * Append a log entry to an admin script execution's results.logs array
162
+ *
163
+ * @param {string|number} processId - The admin script execution ID
164
+ * @param {Object} logEntry - Log entry { level, message, data, timestamp }
165
+ * @returns {Promise<Object>} Updated admin script execution record
166
+ */
167
+ async appendExecutionLog(processId, logEntry) {
168
+ try {
169
+ const updated = await adminScriptExecutionRepository.appendExecutionLog(
170
+ processId,
171
+ logEntry
172
+ );
173
+ return updated;
174
+ } catch (error) {
175
+ return mapErrorToResponse(error);
176
+ }
177
+ },
178
+
179
+ /**
180
+ * Complete an admin script execution
181
+ * Updates state, output, error, and metrics
182
+ *
183
+ * @param {string|number} processId - The admin script execution ID
184
+ * @param {Object} params - Completion parameters
185
+ * @param {string} [params.state] - Final state ('COMPLETED', 'FAILED')
186
+ * @param {Object} [params.output] - Script output/result (stored in results.output)
187
+ * @param {Object} [params.error] - Error details { name, message, stack } (stored in results.error)
188
+ * @param {Object} [params.metrics] - Performance metrics { startTime, endTime, durationMs } (stored in results.metrics)
189
+ * @param {Array} [params.logs] - Execution log entries (stored in results.logs)
190
+ * @returns {Promise<Object>} { success: true } or error
191
+ */
192
+ async completeExecution(
193
+ processId,
194
+ { state, output, error, metrics, logs }
195
+ ) {
196
+ try {
197
+ if (state) {
198
+ await adminScriptExecutionRepository.updateExecutionState(
199
+ processId,
200
+ state
201
+ );
202
+ }
203
+
204
+ // Merge output/error/metrics/logs into the results JSON in one write
205
+ const resultsUpdate = {};
206
+ if (output !== undefined) resultsUpdate.output = output;
207
+ if (error) resultsUpdate.error = error;
208
+ if (metrics) resultsUpdate.metrics = metrics;
209
+ if (logs) resultsUpdate.logs = logs;
210
+ if (Object.keys(resultsUpdate).length > 0) {
211
+ await adminScriptExecutionRepository.updateExecutionResults(
212
+ processId,
213
+ resultsUpdate
214
+ );
215
+ }
216
+
217
+ return { success: true };
218
+ } catch (err) {
219
+ return mapErrorToResponse(err);
220
+ }
221
+ },
222
+
223
+ // ==================== Schedule Management Commands ====================
224
+
225
+ /**
226
+ * Get schedule by script name
227
+ * Returns database override or null
228
+ *
229
+ * @param {string} scriptName - The script name
230
+ * @returns {Promise<Object|null>} Schedule record or null
231
+ */
232
+ async getScheduleByScriptName(scriptName) {
233
+ try {
234
+ const schedule =
235
+ await scheduleRepository.findScheduleByScriptName(
236
+ scriptName
237
+ );
238
+ return schedule;
239
+ } catch (error) {
240
+ return mapErrorToResponse(error);
241
+ }
242
+ },
243
+
244
+ /**
245
+ * Create or update a schedule (upsert)
246
+ *
247
+ * @param {Object} params - Schedule parameters
248
+ * @param {string} params.scriptName - Name of the script
249
+ * @param {boolean} params.enabled - Whether schedule is enabled
250
+ * @param {string} params.cronExpression - Cron expression
251
+ * @param {string} [params.timezone] - Timezone (default 'UTC')
252
+ * @returns {Promise<Object>} Created or updated schedule
253
+ */
254
+ async upsertSchedule({
255
+ scriptName,
256
+ enabled,
257
+ cronExpression,
258
+ timezone,
259
+ }) {
260
+ try {
261
+ const schedule = await scheduleRepository.upsertSchedule({
262
+ scriptName,
263
+ enabled,
264
+ cronExpression,
265
+ timezone,
266
+ });
267
+ return schedule;
268
+ } catch (error) {
269
+ return mapErrorToResponse(error);
270
+ }
271
+ },
272
+
273
+ /**
274
+ * Delete a schedule by script name
275
+ *
276
+ * @param {string} scriptName - The script name
277
+ * @returns {Promise<Object>} Deletion result
278
+ */
279
+ async deleteSchedule(scriptName) {
280
+ try {
281
+ const result = await scheduleRepository.deleteSchedule(
282
+ scriptName
283
+ );
284
+ return result;
285
+ } catch (error) {
286
+ return mapErrorToResponse(error);
287
+ }
288
+ },
289
+
290
+ /**
291
+ * Update external scheduler information
292
+ *
293
+ * @param {string} scriptName - The script name
294
+ * @param {Object} externalInfo - External schedule information
295
+ * @param {string} [externalInfo.externalScheduleId] - External scheduler ID (e.g., AWS ARN)
296
+ * @param {string} [externalInfo.externalScheduleName] - External scheduler name
297
+ * @returns {Promise<Object>} Updated schedule
298
+ */
299
+ async updateScheduleExternalInfo(
300
+ scriptName,
301
+ { externalScheduleId, externalScheduleName }
302
+ ) {
303
+ try {
304
+ const schedule =
305
+ await scheduleRepository.updateScheduleExternalInfo(
306
+ scriptName,
307
+ {
308
+ externalScheduleId,
309
+ externalScheduleName,
310
+ }
311
+ );
312
+ return schedule;
313
+ } catch (error) {
314
+ return mapErrorToResponse(error);
315
+ }
316
+ },
317
+
318
+ /**
319
+ * Update last triggered timestamp
320
+ * Called when a schedule triggers
321
+ *
322
+ * @param {string} scriptName - The script name
323
+ * @param {Date} [timestamp] - Trigger timestamp (default: now)
324
+ * @returns {Promise<Object>} Updated schedule
325
+ */
326
+ async updateScheduleLastTriggered(scriptName, timestamp) {
327
+ try {
328
+ const schedule =
329
+ await scheduleRepository.updateScheduleLastTriggered(
330
+ scriptName,
331
+ timestamp
332
+ );
333
+ return schedule;
334
+ } catch (error) {
335
+ return mapErrorToResponse(error);
336
+ }
337
+ },
338
+
339
+ /**
340
+ * List all schedules
341
+ *
342
+ * @param {Object} [options] - Query options
343
+ * @param {boolean} [options.enabledOnly] - Only return enabled schedules
344
+ * @returns {Promise<Array>} Array of schedule records
345
+ */
346
+ async listSchedules(options = {}) {
347
+ try {
348
+ const schedules = await scheduleRepository.listSchedules(
349
+ options
350
+ );
351
+ return schedules;
352
+ } catch (error) {
353
+ return [];
354
+ }
355
+ },
356
+ };
357
+ }
358
+
359
+ module.exports = { createAdminScriptCommands };
@@ -0,0 +1,262 @@
1
+ const {
2
+ createCredentialRepository,
3
+ } = require('../../credential/repositories/credential-repository-factory');
4
+
5
+ const ERROR_CODE_MAP = {
6
+ CREDENTIAL_NOT_FOUND: 404,
7
+ INVALID_CREDENTIAL_DATA: 400,
8
+ };
9
+
10
+ function mapErrorToResponse(error) {
11
+ const status = ERROR_CODE_MAP[error?.code] || 500;
12
+ return {
13
+ error: status,
14
+ reason: error?.message,
15
+ code: error?.code,
16
+ };
17
+ }
18
+
19
+ /**
20
+ * Create credential command factory
21
+ *
22
+ * NOTE: This is an internal API. Integration developers should use createFriggCommands() instead.
23
+ *
24
+ * @returns {Object} Credential command object with CRUD operations
25
+ */
26
+ function createCredentialCommands() {
27
+ const credRepo = createCredentialRepository();
28
+
29
+ return {
30
+ /**
31
+ * Create a new credential
32
+ * @param {Object} params
33
+ * @param {string} params.userId - User ID who owns this credential
34
+ * @param {string} params.externalId - External identifier from the API module
35
+ * @param {string} params.access_token - OAuth access token
36
+ * @param {string} [params.refresh_token] - OAuth refresh token
37
+ * @param {string} [params.domain] - Domain for the credential
38
+ * @param {boolean} [params.authIsValid=true] - Whether authentication is valid
39
+ * @returns {Promise<Object>} Created credential object
40
+ */
41
+ async createCredential({
42
+ userId,
43
+ externalId,
44
+ access_token,
45
+ refresh_token,
46
+ domain,
47
+ authIsValid = true,
48
+ } = {}) {
49
+ try {
50
+ if (!userId || !externalId || !access_token) {
51
+ const error = new Error(
52
+ 'userId, externalId, and access_token are required'
53
+ );
54
+ error.code = 'INVALID_CREDENTIAL_DATA';
55
+ throw error;
56
+ }
57
+
58
+ const credentialData = {
59
+ identifiers: { userId, externalId },
60
+ details: {
61
+ access_token,
62
+ authIsValid,
63
+ },
64
+ };
65
+
66
+ if (refresh_token) {
67
+ credentialData.details.refresh_token = refresh_token;
68
+ }
69
+ if (domain) {
70
+ credentialData.details.domain = domain;
71
+ }
72
+
73
+ const credential = await credRepo.upsertCredential(
74
+ credentialData
75
+ );
76
+
77
+ return {
78
+ id: credential.id,
79
+ userId: credential.userId,
80
+ externalId: credential.externalId,
81
+ access_token: credential.access_token,
82
+ refresh_token: credential.refresh_token,
83
+ authIsValid: credential.authIsValid,
84
+ };
85
+ } catch (error) {
86
+ return mapErrorToResponse(error);
87
+ }
88
+ },
89
+
90
+ /**
91
+ * Find a credential by filter criteria
92
+ * @param {Object} filter
93
+ * @param {string} [filter.userId] - User ID to search for
94
+ * @param {string} [filter.externalId] - External ID to search for
95
+ * @param {string} [filter.credentialId] - Credential ID to search for
96
+ * @returns {Promise<Object|null>} Credential object or null if not found
97
+ */
98
+ async findCredential(filter = {}) {
99
+ try {
100
+ if (
101
+ !filter.userId &&
102
+ !filter.externalId &&
103
+ !filter.credentialId
104
+ ) {
105
+ const error = new Error(
106
+ 'At least one filter criterion is required'
107
+ );
108
+ error.code = 'INVALID_CREDENTIAL_DATA';
109
+ throw error;
110
+ }
111
+
112
+ const credential = await credRepo.findCredential(filter);
113
+
114
+ if (!credential) {
115
+ return null;
116
+ }
117
+
118
+ return {
119
+ id: credential.id,
120
+ userId: credential.userId,
121
+ externalId: credential.externalId,
122
+ access_token: credential.access_token,
123
+ refresh_token: credential.refresh_token,
124
+ authIsValid: credential.authIsValid,
125
+ domain: credential.domain,
126
+ };
127
+ } catch (error) {
128
+ return mapErrorToResponse(error);
129
+ }
130
+ },
131
+
132
+ /**
133
+ * Update a credential by ID
134
+ * @param {string} credentialId - Credential ID to update
135
+ * @param {Object} updates - Fields to update
136
+ * @returns {Promise<Object>} Updated credential object
137
+ */
138
+ async updateCredential(credentialId, updates) {
139
+ try {
140
+ if (!credentialId) {
141
+ const error = new Error('credentialId is required');
142
+ error.code = 'INVALID_CREDENTIAL_DATA';
143
+ throw error;
144
+ }
145
+
146
+ const credential = await credRepo.updateCredential(
147
+ credentialId,
148
+ updates
149
+ );
150
+
151
+ if (!credential) {
152
+ const error = new Error(
153
+ `Credential ${credentialId} not found`
154
+ );
155
+ error.code = 'CREDENTIAL_NOT_FOUND';
156
+ throw error;
157
+ }
158
+
159
+ return {
160
+ id: credential.id,
161
+ userId: credential.userId,
162
+ externalId: credential.externalId,
163
+ access_token: credential.access_token,
164
+ refresh_token: credential.refresh_token,
165
+ authIsValid: credential.authIsValid,
166
+ domain: credential.domain,
167
+ };
168
+ } catch (error) {
169
+ return mapErrorToResponse(error);
170
+ }
171
+ },
172
+
173
+ /**
174
+ * Update authentication status for a credential
175
+ * @param {string} credentialId - Credential ID to update
176
+ * @param {boolean} isValid - Whether authentication is valid
177
+ * @returns {Promise<Object>} Result object with success flag
178
+ */
179
+ async updateAuthenticationStatus(credentialId, isValid) {
180
+ try {
181
+ if (!credentialId) {
182
+ const error = new Error('credentialId is required');
183
+ error.code = 'INVALID_CREDENTIAL_DATA';
184
+ throw error;
185
+ }
186
+
187
+ await credRepo.updateAuthenticationStatus(
188
+ credentialId,
189
+ isValid
190
+ );
191
+
192
+ return { success: true };
193
+ } catch (error) {
194
+ return mapErrorToResponse(error);
195
+ }
196
+ },
197
+
198
+ /**
199
+ * Delete a credential by ID
200
+ * @param {string} credentialId - Credential ID to delete
201
+ * @returns {Promise<Object>} Result object with success flag
202
+ */
203
+ async deleteCredential(credentialId) {
204
+ try {
205
+ if (!credentialId) {
206
+ const error = new Error('credentialId is required');
207
+ error.code = 'INVALID_CREDENTIAL_DATA';
208
+ throw error;
209
+ }
210
+
211
+ await credRepo.deleteCredentialById(credentialId);
212
+
213
+ return { success: true };
214
+ } catch (error) {
215
+ return mapErrorToResponse(error);
216
+ }
217
+ },
218
+
219
+ /**
220
+ * Count credentials active (updatedAt >= since) grouped by integration
221
+ * type, derived from the related Entity.moduleName. Returns a non-secret
222
+ * projection only — never reads or decrypts credential secrets.
223
+ *
224
+ * @param {Object} params
225
+ * @param {Date} [params.since] - Lower bound on updatedAt
226
+ * @returns {Promise<Array<{ integrationType: string, count: number }>>}
227
+ */
228
+ async countActiveByType({ since } = {}) {
229
+ try {
230
+ return await credRepo.countActiveByType({ since });
231
+ } catch (error) {
232
+ return mapErrorToResponse(error);
233
+ }
234
+ },
235
+
236
+ /**
237
+ * Delete a credential by ID (alias for deleteCredential)
238
+ * @param {string} credentialId - Credential ID to delete
239
+ * @returns {Promise<Object>} Result object with success flag
240
+ */
241
+ async deleteCredentialById(credentialId) {
242
+ try {
243
+ if (!credentialId) {
244
+ const error = new Error('credentialId is required');
245
+ error.code = 'INVALID_CREDENTIAL_DATA';
246
+ throw error;
247
+ }
248
+
249
+ await credRepo.deleteCredentialById(credentialId);
250
+
251
+ return { success: true };
252
+ } catch (error) {
253
+ return mapErrorToResponse(error);
254
+ }
255
+ },
256
+ };
257
+ }
258
+
259
+ module.exports = {
260
+ createCredentialCommands,
261
+ ERROR_CODE_MAP,
262
+ };