@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,73 @@
1
+ /**
2
+ * Wrap a telemetry service so an integration instance's emissions automatically
3
+ * carry its context — with no per-call boilerplate. Two channels are filled:
4
+ * - `integration_type` onto attributes (the one bounded, low-cardinality label);
5
+ * - the full identifier set onto the bus `context` arg (integrationId, userId,
6
+ * version, …), which the usage rollup and traces read.
7
+ *
8
+ * So integration code writes `this.telemetry.count('records.synced', n, { entity })`
9
+ * or `this.telemetry.event('thing')` and both channels are populated. An
10
+ * explicitly passed context still wins (e.g. a requester attaching a per-call
11
+ * `url`), and high-cardinality ids ride the bus context only, never metric
12
+ * labels (Cardinality note).
13
+ *
14
+ * @param {object} base The underlying telemetry service.
15
+ * @param {() => object} getContext Lazy accessor for the instance's context.
16
+ */
17
+ function bindTelemetryContext(base, getContext) {
18
+ if (!base) return base;
19
+
20
+ const readContext = () => {
21
+ try {
22
+ return (getContext && getContext()) || undefined;
23
+ } catch (_) {
24
+ return undefined;
25
+ }
26
+ };
27
+
28
+ const withType = (attributes, ctx) => {
29
+ const integrationType = ctx && ctx.integrationType;
30
+ if (!integrationType || 'integration_type' in attributes) {
31
+ return attributes;
32
+ }
33
+ return { integration_type: integrationType, ...attributes };
34
+ };
35
+
36
+ const resolveContext = (context, ctx) =>
37
+ context !== undefined ? context : ctx;
38
+
39
+ return {
40
+ // Single source of truth for the instance context, so callers (e.g.
41
+ // instrumentHandler) read it here instead of gathering it separately.
42
+ getContext: () => readContext() || {},
43
+ count(name, value = 1, attributes = {}, context) {
44
+ const ctx = readContext();
45
+ return base.count(
46
+ name,
47
+ value,
48
+ withType(attributes, ctx),
49
+ resolveContext(context, ctx)
50
+ );
51
+ },
52
+ event(name, attributes = {}, context) {
53
+ const ctx = readContext();
54
+ return base.event(
55
+ name,
56
+ withType(attributes, ctx),
57
+ resolveContext(context, ctx)
58
+ );
59
+ },
60
+ span: (...args) => base.span(...args),
61
+ startSpan: (...args) => base.startSpan(...args),
62
+ withContext: (...args) => base.withContext(...args),
63
+ on: (...args) => base.on(...args),
64
+ forceFlush: (...args) => base.forceFlush(...args),
65
+ shutdown: (...args) =>
66
+ typeof base.shutdown === 'function'
67
+ ? base.shutdown(...args)
68
+ : undefined,
69
+ isEnabled: (...args) => base.isEnabled(...args),
70
+ };
71
+ }
72
+
73
+ module.exports = { bindTelemetryContext };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Canonical usage-counter vocabulary.
3
+ *
4
+ * These core-owned, versioned keys are the ONLY metrics guaranteed comparable
5
+ * *across* integration types — they power ADR-010's apples-to-apples comparison
6
+ * report. Custom keys (declared in an integration's `Definition.usage.custom`)
7
+ * are comparable only *within* an integration type.
8
+ *
9
+ * The registry is **additive**: new keys may be added, existing keys never
10
+ * change or are removed, so existing reports never break.
11
+ *
12
+ * `dims` are the bounded dimensions a counter may carry (Cardinality note) —
13
+ * high-cardinality ids (integrationId, userId) never appear here.
14
+ */
15
+ const CANONICAL_COUNTERS = {
16
+ 'records.synced': {
17
+ unit: 'count',
18
+ label: 'Records synced',
19
+ dims: ['entity'],
20
+ },
21
+ 'webhooks.received': {
22
+ unit: 'count',
23
+ label: 'Webhooks received',
24
+ dims: ['event'],
25
+ },
26
+ 'workflows.invoked': {
27
+ unit: 'count',
28
+ label: 'Workflows invoked',
29
+ dims: ['workflow'],
30
+ },
31
+ 'api.requests': {
32
+ unit: 'count',
33
+ label: 'API requests',
34
+ dims: ['endpoint', 'status'],
35
+ },
36
+ user_actions: { unit: 'count', label: 'User actions', dims: ['action'] },
37
+ };
38
+
39
+ // NOTE: the framework-signal → canonical mapping lives in the usage rollup
40
+ // subscriber (METRIC_TO_CANONICAL, keyed by the actual emitted metric names).
41
+ // `records.synced` / `workflows.invoked` have no auto-signal — they are
42
+ // explicit-only (`this.telemetry.count(...)`), so a canonical counter is never
43
+ // shipped that silently stays at zero.
44
+
45
+ function isCanonicalCounter(name) {
46
+ return Object.prototype.hasOwnProperty.call(CANONICAL_COUNTERS, name);
47
+ }
48
+
49
+ module.exports = {
50
+ CANONICAL_COUNTERS,
51
+ isCanonicalCounter,
52
+ };
@@ -0,0 +1,85 @@
1
+ // Telemetry exporters — build the OTel { traceExporter, metricExporter } pair
2
+ // for one destination. OTel SDK packages are require'd lazily INSIDE the
3
+ // builders, so loading this module pulls in zero OTel (cold-start invariant).
4
+
5
+ function joinPath(base, path) {
6
+ return `${String(base).replace(/\/$/, '')}${path}`;
7
+ }
8
+
9
+ /**
10
+ * Normalize a descriptor to an OTLP target { endpoint, headers }, folding in
11
+ * vendor presets (Honeycomb). Pure — no OTel required — so it stays unit-testable.
12
+ */
13
+ function otlpTarget({ type, endpoint, headers, apiKey } = {}) {
14
+ if (type === 'honeycomb') {
15
+ return {
16
+ endpoint: endpoint || 'https://api.honeycomb.io',
17
+ headers: apiKey ? { 'x-honeycomb-team': apiKey } : headers,
18
+ };
19
+ }
20
+ return { endpoint, headers };
21
+ }
22
+
23
+ function buildOtlp(descriptor = {}) {
24
+ const {
25
+ OTLPTraceExporter,
26
+ } = require('@opentelemetry/exporter-trace-otlp-http');
27
+ const {
28
+ OTLPMetricExporter,
29
+ } = require('@opentelemetry/exporter-metrics-otlp-http');
30
+ const { endpoint, headers } = otlpTarget(descriptor);
31
+ // With no endpoint the SDK falls back to OTEL_EXPORTER_OTLP_ENDPOINT, so
32
+ // leave `url` unset in that case.
33
+ const options = (path) => ({
34
+ ...(endpoint ? { url: joinPath(endpoint, path) } : {}),
35
+ ...(headers ? { headers } : {}),
36
+ });
37
+ return {
38
+ traceExporter: new OTLPTraceExporter(options('/v1/traces')),
39
+ metricExporter: new OTLPMetricExporter(options('/v1/metrics')),
40
+ };
41
+ }
42
+
43
+ function buildConsole() {
44
+ const { ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-base');
45
+ const { ConsoleMetricExporter } = require('@opentelemetry/sdk-metrics');
46
+ return {
47
+ traceExporter: new ConsoleSpanExporter(),
48
+ metricExporter: new ConsoleMetricExporter(),
49
+ };
50
+ }
51
+
52
+ // type → builder. Add a destination = add one entry. Datadog ingests OTLP/HTTP
53
+ // natively; Honeycomb is an OTLP preset resolved in otlpTarget.
54
+ const EXPORTERS = {
55
+ otlp: buildOtlp,
56
+ datadog: buildOtlp,
57
+ honeycomb: buildOtlp,
58
+ console: buildConsole,
59
+ };
60
+
61
+ /**
62
+ * Resolve a telemetry descriptor to its { traceExporter, metricExporter } pair.
63
+ * Pre-built instances (tests / advanced adopters) win over `type`; an unknown or
64
+ * absent type falls back to plain OTLP (which itself falls back to the standard
65
+ * OTLP env var). The own-property check keeps a `type` matching an
66
+ * Object.prototype member ('constructor', 'toString', …) from resolving an
67
+ * inherited key.
68
+ */
69
+ function resolveExporter(descriptor = {}) {
70
+ if (descriptor.traceExporter || descriptor.metricExporter) {
71
+ return {
72
+ traceExporter: descriptor.traceExporter || null,
73
+ metricExporter: descriptor.metricExporter || null,
74
+ };
75
+ }
76
+ const build = Object.prototype.hasOwnProperty.call(
77
+ EXPORTERS,
78
+ descriptor.type
79
+ )
80
+ ? EXPORTERS[descriptor.type]
81
+ : buildOtlp;
82
+ return build(descriptor);
83
+ }
84
+
85
+ module.exports = { resolveExporter, EXPORTERS, otlpTarget, joinPath };
@@ -0,0 +1,26 @@
1
+ // Public telemetry surface. Framework-internal modules (adapters, bus, config,
2
+ // exporters, subscribers, rollup) are deep-required by their consumers, not
3
+ // re-exported here — every barrel export is semver surface.
4
+ const { createTelemetry } = require('./telemetry-service');
5
+ const {
6
+ getTelemetry,
7
+ setTelemetryForTests,
8
+ resetTelemetryRuntimeForTests,
9
+ } = require('./telemetry-runtime');
10
+ const { bindTelemetryContext } = require('./bind-telemetry-context');
11
+ const { instrumentHandler } = require('./instrument-handler');
12
+ const {
13
+ CANONICAL_COUNTERS,
14
+ isCanonicalCounter,
15
+ } = require('./canonical-counters');
16
+
17
+ module.exports = {
18
+ createTelemetry,
19
+ getTelemetry,
20
+ setTelemetryForTests,
21
+ resetTelemetryRuntimeForTests,
22
+ bindTelemetryContext,
23
+ instrumentHandler,
24
+ CANONICAL_COUNTERS,
25
+ isCanonicalCounter,
26
+ };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Wraps a single integration handler invocation with a span + the
3
+ * `frigg.handler.invocations` counter. Shared by the two
4
+ * dispatch seams — `IntegrationBase.send()` and `IntegrationEventDispatcher` —
5
+ * so both paths are instrumented identically.
6
+ *
7
+ * Cardinality discipline: the metric is keyed by the **bounded event type**
8
+ * (USER_ACTION / CRON / QUEUE / WEBHOOK / LIFE_CYCLE_EVENT), never the specific
9
+ * event/action name. High-cardinality ids (integrationId, userId) ride span
10
+ * baggage via `telemetry.withContext`, never metric attributes. The full event
11
+ * name is kept on the span only.
12
+ *
13
+ * @param {object|null} telemetry Bound telemetry service (no-op-safe; null → just
14
+ * runs fn). The context is read from `telemetry.getContext()` — the per-instance
15
+ * bound wrapper carries it; a raw service degrades to 'unknown'.
16
+ * @param {{event: string, eventType: string}} descriptor Event name + bounded type.
17
+ * @param {Function} fn The handler invocation.
18
+ */
19
+ async function instrumentHandler(telemetry, descriptor = {}, fn) {
20
+ if (!telemetry || typeof telemetry.span !== 'function') {
21
+ return fn();
22
+ }
23
+
24
+ const context =
25
+ typeof telemetry.getContext === 'function'
26
+ ? telemetry.getContext()
27
+ : {};
28
+ const integrationType = context.integrationType || 'unknown';
29
+ const eventType = descriptor.eventType || 'unknown';
30
+ const eventName = descriptor.event;
31
+
32
+ const runInstrumented = () =>
33
+ telemetry.span(`frigg.handler.${eventType}`, async (span) => {
34
+ if (span && typeof span.setAttributes === 'function') {
35
+ span.setAttributes({
36
+ integration_type: integrationType,
37
+ event: eventType,
38
+ event_name: eventName,
39
+ });
40
+ }
41
+ // `event_name` (potentially high-cardinality action id) rides the
42
+ // bus-only context — used by North Star derived-from-trace matching,
43
+ // never a metric label.
44
+ const busContext = { event_name: eventName };
45
+ try {
46
+ const result = await fn();
47
+ telemetry.count(
48
+ 'frigg.handler.invocations',
49
+ 1,
50
+ {
51
+ integration_type: integrationType,
52
+ event: eventType,
53
+ status: 'ok',
54
+ },
55
+ busContext
56
+ );
57
+ return result;
58
+ } catch (err) {
59
+ telemetry.count(
60
+ 'frigg.handler.invocations',
61
+ 1,
62
+ {
63
+ integration_type: integrationType,
64
+ event: eventType,
65
+ status: 'error',
66
+ },
67
+ busContext
68
+ );
69
+ throw err;
70
+ }
71
+ });
72
+
73
+ if (typeof telemetry.withContext === 'function') {
74
+ return telemetry.withContext(
75
+ {
76
+ integrationId: context.integrationId,
77
+ userId: context.userId,
78
+ integrationType: context.integrationType,
79
+ version: context.version,
80
+ },
81
+ runInstrumented
82
+ );
83
+ }
84
+ return runInstrumented();
85
+ }
86
+
87
+ module.exports = { instrumentHandler };
@@ -0,0 +1,67 @@
1
+ const { createTelemetryEventBus } = require('./telemetry-event-bus');
2
+ const {
3
+ runWithTelemetryContext,
4
+ mergeTelemetryContext,
5
+ } = require('./telemetry-context');
6
+
7
+ /**
8
+ * No-op telemetry adapter: the default when no exporter is configured, so
9
+ * telemetry "rides for free". Imports **zero** OpenTelemetry packages (guarded by
10
+ * a require-graph test) — the no-op path never loads the OTel SDK, protecting
11
+ * Lambda cold-start. The internal event bus is still active: `count`/`event` are
12
+ * mirrored onto it so the durable usage rollup + plugin taps work even with
13
+ * export off (emitting to a bus with no subscribers is cheap).
14
+ */
15
+ class NoOpTelemetry {
16
+ constructor({ bus = createTelemetryEventBus() } = {}) {
17
+ this._bus = bus;
18
+ }
19
+
20
+ count(name, value = 1, attributes = {}, context) {
21
+ const merged = mergeTelemetryContext(context);
22
+ const payload = { name, value, attributes };
23
+ if (merged) payload.context = merged;
24
+ this._bus.emit('metric', payload);
25
+ }
26
+
27
+ event(name, attributes = {}, context) {
28
+ const merged = mergeTelemetryContext(context);
29
+ const payload = { name, attributes };
30
+ if (merged) payload.context = merged;
31
+ this._bus.emit('event', payload);
32
+ }
33
+
34
+ async span(_name, fn) {
35
+ return typeof fn === 'function' ? fn() : undefined;
36
+ }
37
+
38
+ startSpan() {
39
+ return {
40
+ setAttributes() {},
41
+ setAttribute() {},
42
+ recordException() {},
43
+ setStatus() {},
44
+ end() {},
45
+ };
46
+ }
47
+
48
+ async withContext(context, fn) {
49
+ return runWithTelemetryContext(context, () =>
50
+ typeof fn === 'function' ? fn() : undefined
51
+ );
52
+ }
53
+
54
+ on(eventType, callback) {
55
+ return this._bus.on(eventType, callback);
56
+ }
57
+
58
+ async forceFlush() {}
59
+
60
+ async shutdown() {}
61
+
62
+ isEnabled() {
63
+ return false;
64
+ }
65
+ }
66
+
67
+ module.exports = { NoOpTelemetry };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Adopter North Star metric. A North Star simply references
3
+ * a usage-counter key (canonical or custom); its value is then read like any
4
+ * other counter via `frigg.usage.getTotalsByDimension({ metric: northStarKey })`. It is
5
+ * populated either by (a) direct emission of that counter, or (b) derived from a
6
+ * framework trace signal — this module implements (b) as a small bus subscriber
7
+ * that emits the North Star counter when a configured signal matches.
8
+ */
9
+
10
+ /** Resolve the North Star counter entry for an integration type (byType wins). */
11
+ function resolveNorthStarEntry(northStar, integrationType) {
12
+ if (!northStar) return null;
13
+ return (
14
+ (northStar.byType && northStar.byType[integrationType]) ||
15
+ northStar.default ||
16
+ null
17
+ );
18
+ }
19
+
20
+ /** The set of counter keys any North Star references — added to trackedMetrics. */
21
+ function northStarKeys(northStar) {
22
+ const keys = new Set();
23
+ if (!northStar) return keys;
24
+ if (northStar.default?.name) keys.add(northStar.default.name);
25
+ for (const entry of Object.values(northStar.byType || {})) {
26
+ if (entry?.name) keys.add(entry.name);
27
+ }
28
+ return keys;
29
+ }
30
+
31
+ function matchesDeriveFrom(
32
+ deriveFrom,
33
+ { name, attributes = {}, context = {} }
34
+ ) {
35
+ if (!deriveFrom) return false;
36
+
37
+ if (deriveFrom.userAction) {
38
+ const rule = deriveFrom.userAction;
39
+ return (
40
+ name === 'frigg.handler.invocations' &&
41
+ attributes.event === 'USER_ACTION' &&
42
+ (!rule.action || context.event_name === rule.action)
43
+ );
44
+ }
45
+
46
+ if (deriveFrom.apiRequest) {
47
+ const rule = deriveFrom.apiRequest;
48
+ return (
49
+ name === 'frigg.apimodule.requests' &&
50
+ (!rule.method || attributes.method === rule.method) &&
51
+ (!rule.endpoint ||
52
+ (typeof context.url === 'string' &&
53
+ context.url.includes(rule.endpoint)))
54
+ );
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+ /**
61
+ * Subscribe to the bus and emit the North Star counter whenever a configured
62
+ * `deriveFrom` signal matches (config-only, no integration code). The emitted
63
+ * counter flows back through the bus to the usage rollup like any other metric.
64
+ */
65
+ function createNorthStarDerivationSubscriber({ telemetry, northStar }) {
66
+ if (!telemetry || !northStar) return { unsubscribe() {} };
67
+
68
+ // Hoisted — the referenced-key set is fixed for the life of the subscriber.
69
+ const keys = northStarKeys(northStar);
70
+
71
+ function onMetric(payload) {
72
+ try {
73
+ // Never react to a North Star counter's own emission (no loop).
74
+ if (keys.has(payload.name)) return;
75
+
76
+ const integrationType =
77
+ payload.context?.integrationType ||
78
+ payload.attributes?.integration_type ||
79
+ null;
80
+ const entry = resolveNorthStarEntry(northStar, integrationType);
81
+ if (!entry || !entry.deriveFrom) return;
82
+ if (!matchesDeriveFrom(entry.deriveFrom, payload)) return;
83
+
84
+ telemetry.count(
85
+ entry.name,
86
+ 1,
87
+ integrationType ? { integration_type: integrationType } : {},
88
+ payload.context
89
+ );
90
+ } catch (_) {
91
+ // Derivation must never break emission.
92
+ }
93
+ }
94
+
95
+ const unsubscribe = telemetry.on('metric', onMetric);
96
+ return { unsubscribe };
97
+ }
98
+
99
+ module.exports = {
100
+ resolveNorthStarEntry,
101
+ northStarKeys,
102
+ createNorthStarDerivationSubscriber,
103
+ };