@friggframework/core 2.0.0-next.1 → 2.0.0-next.100

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 (342) hide show
  1. package/CLAUDE.md +702 -0
  2. package/README.md +959 -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 +166 -0
  7. package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +228 -0
  8. package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +268 -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 +358 -0
  16. package/application/commands/credential-commands.js +245 -0
  17. package/application/commands/entity-commands.js +336 -0
  18. package/application/commands/integration-commands.js +343 -0
  19. package/application/commands/process-commands.js +135 -0
  20. package/application/commands/scheduler-commands.js +263 -0
  21. package/application/commands/user-commands.js +312 -0
  22. package/application/index.js +82 -0
  23. package/assertions/index.js +0 -3
  24. package/core/CLAUDE.md +690 -0
  25. package/core/Worker.js +60 -24
  26. package/core/create-handler.js +84 -6
  27. package/credential/repositories/credential-repository-documentdb.js +304 -0
  28. package/credential/repositories/credential-repository-factory.js +54 -0
  29. package/credential/repositories/credential-repository-interface.js +98 -0
  30. package/credential/repositories/credential-repository-mongo.js +269 -0
  31. package/credential/repositories/credential-repository-postgres.js +287 -0
  32. package/credential/repositories/credential-repository.js +300 -0
  33. package/credential/use-cases/get-credential-for-user.js +25 -0
  34. package/credential/use-cases/update-authentication-status.js +15 -0
  35. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  36. package/database/adapters/lambda-invoker.js +97 -0
  37. package/database/config.js +154 -0
  38. package/database/documentdb-encryption-service.js +330 -0
  39. package/database/documentdb-utils.js +136 -0
  40. package/database/encryption/README.md +839 -0
  41. package/database/encryption/documentdb-encryption-service.md +3575 -0
  42. package/database/encryption/encryption-schema-registry.js +401 -0
  43. package/database/encryption/field-encryption-service.js +254 -0
  44. package/database/encryption/logger.js +79 -0
  45. package/database/encryption/prisma-encryption-extension.js +230 -0
  46. package/database/index.js +21 -21
  47. package/database/prisma.js +182 -0
  48. package/database/repositories/health-check-repository-documentdb.js +138 -0
  49. package/database/repositories/health-check-repository-factory.js +48 -0
  50. package/database/repositories/health-check-repository-interface.js +82 -0
  51. package/database/repositories/health-check-repository-mongodb.js +89 -0
  52. package/database/repositories/health-check-repository-postgres.js +82 -0
  53. package/database/repositories/migration-status-repository-s3.js +137 -0
  54. package/database/use-cases/check-database-health-use-case.js +29 -0
  55. package/database/use-cases/check-database-state-use-case.js +81 -0
  56. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  57. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  58. package/database/use-cases/get-migration-status-use-case.js +93 -0
  59. package/database/use-cases/run-database-migration-use-case.js +139 -0
  60. package/database/use-cases/test-encryption-use-case.js +253 -0
  61. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  62. package/database/utils/mongodb-collection-utils.js +94 -0
  63. package/database/utils/mongodb-schema-init.js +108 -0
  64. package/database/utils/prisma-runner.js +477 -0
  65. package/database/utils/prisma-schema-parser.js +182 -0
  66. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  67. package/encrypt/Cryptor.js +34 -168
  68. package/encrypt/index.js +1 -2
  69. package/errors/client-safe-error.js +26 -0
  70. package/errors/fetch-error.js +15 -7
  71. package/errors/index.js +2 -0
  72. package/generated/prisma-mongodb/client.d.ts +1 -0
  73. package/generated/prisma-mongodb/client.js +5 -0
  74. package/generated/prisma-mongodb/default.d.ts +1 -0
  75. package/generated/prisma-mongodb/default.js +5 -0
  76. package/generated/prisma-mongodb/edge.d.ts +1 -0
  77. package/generated/prisma-mongodb/edge.js +374 -0
  78. package/generated/prisma-mongodb/index-browser.js +356 -0
  79. package/generated/prisma-mongodb/index.d.ts +25667 -0
  80. package/generated/prisma-mongodb/index.js +399 -0
  81. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  82. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  83. package/generated/prisma-mongodb/package.json +183 -0
  84. package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
  85. package/generated/prisma-mongodb/runtime/edge.js +35 -0
  86. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  87. package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
  88. package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
  89. package/generated/prisma-mongodb/runtime/library.js +147 -0
  90. package/generated/prisma-mongodb/runtime/react-native.js +84 -0
  91. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
  92. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
  93. package/generated/prisma-mongodb/schema.prisma +432 -0
  94. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
  95. package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
  96. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  97. package/generated/prisma-mongodb/wasm.js +381 -0
  98. package/generated/prisma-postgresql/client.d.ts +1 -0
  99. package/generated/prisma-postgresql/client.js +5 -0
  100. package/generated/prisma-postgresql/default.d.ts +1 -0
  101. package/generated/prisma-postgresql/default.js +5 -0
  102. package/generated/prisma-postgresql/edge.d.ts +1 -0
  103. package/generated/prisma-postgresql/edge.js +395 -0
  104. package/generated/prisma-postgresql/index-browser.js +377 -0
  105. package/generated/prisma-postgresql/index.d.ts +28455 -0
  106. package/generated/prisma-postgresql/index.js +420 -0
  107. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  108. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  109. package/generated/prisma-postgresql/package.json +183 -0
  110. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  111. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  112. package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
  113. package/generated/prisma-postgresql/runtime/edge.js +35 -0
  114. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  115. package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
  116. package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
  117. package/generated/prisma-postgresql/runtime/library.js +147 -0
  118. package/generated/prisma-postgresql/runtime/react-native.js +84 -0
  119. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
  120. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
  121. package/generated/prisma-postgresql/schema.prisma +414 -0
  122. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
  123. package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
  124. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  125. package/generated/prisma-postgresql/wasm.js +402 -0
  126. package/handlers/WEBHOOKS.md +653 -0
  127. package/handlers/app-definition-loader.js +43 -0
  128. package/handlers/app-handler-helpers.js +57 -0
  129. package/handlers/backend-utils.js +316 -0
  130. package/handlers/database-migration-handler.js +227 -0
  131. package/handlers/integration-event-dispatcher.js +54 -0
  132. package/handlers/middleware/admin-auth.js +73 -0
  133. package/handlers/routers/HEALTHCHECK.md +342 -0
  134. package/handlers/routers/auth.js +15 -0
  135. package/handlers/routers/db-migration.handler.js +29 -0
  136. package/handlers/routers/db-migration.js +311 -0
  137. package/handlers/routers/health.js +518 -0
  138. package/handlers/routers/integration-defined-routers.js +117 -0
  139. package/handlers/routers/integration-webhook-routers.js +67 -0
  140. package/handlers/routers/reporting.js +9 -0
  141. package/handlers/routers/user.js +63 -0
  142. package/handlers/routers/websocket.js +57 -0
  143. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  144. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  145. package/handlers/workers/db-migration.js +352 -0
  146. package/handlers/workers/dlq-processor.js +63 -0
  147. package/handlers/workers/integration-defined-workers.js +30 -0
  148. package/index.js +111 -50
  149. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
  150. package/infrastructure/scheduler/index.js +33 -0
  151. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  152. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  153. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  154. package/integrations/EXTENSIONS.md +240 -0
  155. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  156. package/integrations/extension.js +254 -0
  157. package/integrations/index.js +20 -10
  158. package/integrations/integration-base.js +619 -72
  159. package/integrations/integration-router.js +460 -218
  160. package/integrations/options.js +3 -4
  161. package/integrations/repositories/config-patch-shared.js +43 -0
  162. package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
  163. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  164. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  165. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  166. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  167. package/integrations/repositories/integration-mapping-repository.js +156 -0
  168. package/integrations/repositories/integration-repository-documentdb.js +284 -0
  169. package/integrations/repositories/integration-repository-factory.js +51 -0
  170. package/integrations/repositories/integration-repository-interface.js +173 -0
  171. package/integrations/repositories/integration-repository-mongo.js +414 -0
  172. package/integrations/repositories/integration-repository-postgres.js +452 -0
  173. package/integrations/repositories/process-repository-documentdb.js +311 -0
  174. package/integrations/repositories/process-repository-factory.js +53 -0
  175. package/integrations/repositories/process-repository-interface.js +136 -0
  176. package/integrations/repositories/process-repository-mongo.js +262 -0
  177. package/integrations/repositories/process-repository-postgres.js +380 -0
  178. package/integrations/repositories/process-update-ops-shared.js +112 -0
  179. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  180. package/integrations/tests/doubles/dummy-integration-class.js +113 -0
  181. package/integrations/tests/doubles/test-integration-repository.js +146 -0
  182. package/integrations/use-cases/create-integration.js +215 -0
  183. package/integrations/use-cases/create-process.js +130 -0
  184. package/integrations/use-cases/delete-integration-for-user.js +119 -0
  185. package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
  186. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
  187. package/integrations/use-cases/get-integration-for-user.js +78 -0
  188. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  189. package/integrations/use-cases/get-integration-instance.js +83 -0
  190. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  191. package/integrations/use-cases/get-possible-integrations.js +27 -0
  192. package/integrations/use-cases/get-process.js +89 -0
  193. package/integrations/use-cases/index.js +19 -0
  194. package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
  195. package/integrations/use-cases/load-integration-context.js +71 -0
  196. package/integrations/use-cases/patch-integration-config.js +39 -0
  197. package/integrations/use-cases/process-errors.js +28 -0
  198. package/integrations/use-cases/update-integration-config.js +32 -0
  199. package/integrations/use-cases/update-integration-messages.js +44 -0
  200. package/integrations/use-cases/update-integration-status.js +32 -0
  201. package/integrations/use-cases/update-integration.js +92 -0
  202. package/integrations/use-cases/update-process-metrics.js +216 -0
  203. package/integrations/use-cases/update-process-state.js +163 -0
  204. package/integrations/utils/map-integration-dto.js +37 -0
  205. package/jest-global-setup-noop.js +3 -0
  206. package/jest-global-teardown-noop.js +3 -0
  207. package/logs/logger.js +0 -4
  208. package/{module-plugin → modules}/index.js +0 -10
  209. package/modules/module-factory.js +56 -0
  210. package/modules/module.js +274 -0
  211. package/modules/repositories/module-repository-documentdb.js +350 -0
  212. package/modules/repositories/module-repository-factory.js +40 -0
  213. package/modules/repositories/module-repository-interface.js +145 -0
  214. package/modules/repositories/module-repository-mongo.js +436 -0
  215. package/modules/repositories/module-repository-postgres.js +481 -0
  216. package/modules/repositories/module-repository.js +369 -0
  217. package/modules/requester/api-key.js +52 -0
  218. package/modules/requester/oauth-2.js +396 -0
  219. package/modules/requester/requester.js +285 -0
  220. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  221. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  222. package/modules/tests/doubles/test-module-factory.js +16 -0
  223. package/modules/tests/doubles/test-module-repository.js +39 -0
  224. package/modules/use-cases/get-entities-for-user.js +32 -0
  225. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  226. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  227. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  228. package/modules/use-cases/get-module.js +74 -0
  229. package/modules/use-cases/process-authorization-callback.js +243 -0
  230. package/modules/use-cases/refresh-entity-options.js +72 -0
  231. package/modules/use-cases/test-module-auth.js +72 -0
  232. package/modules/utils/map-module-dto.js +18 -0
  233. package/package.json +82 -50
  234. package/prisma-mongodb/schema.prisma +432 -0
  235. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  236. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  237. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  238. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  239. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  240. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  241. package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
  242. package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
  243. package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
  244. package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
  245. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  246. package/prisma-postgresql/schema.prisma +414 -0
  247. package/queues/queuer-util.js +103 -21
  248. package/reporting/README.md +86 -0
  249. package/reporting/index.js +17 -0
  250. package/reporting/reporting-router.js +77 -0
  251. package/reporting/repositories/reporting-repository-documentdb.js +127 -0
  252. package/reporting/repositories/reporting-repository-factory.js +35 -0
  253. package/reporting/repositories/reporting-repository-interface.js +16 -0
  254. package/reporting/repositories/reporting-repository-mongo.js +54 -0
  255. package/reporting/repositories/reporting-repository-postgres.js +70 -0
  256. package/reporting/use-cases/index.js +6 -0
  257. package/reporting/use-cases/list-integrations-report.js +142 -0
  258. package/syncs/manager.js +468 -443
  259. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  260. package/syncs/repositories/sync-repository-factory.js +43 -0
  261. package/syncs/repositories/sync-repository-interface.js +109 -0
  262. package/syncs/repositories/sync-repository-mongo.js +239 -0
  263. package/syncs/repositories/sync-repository-postgres.js +319 -0
  264. package/syncs/sync.js +0 -1
  265. package/token/repositories/token-repository-documentdb.js +137 -0
  266. package/token/repositories/token-repository-factory.js +40 -0
  267. package/token/repositories/token-repository-interface.js +131 -0
  268. package/token/repositories/token-repository-mongo.js +219 -0
  269. package/token/repositories/token-repository-postgres.js +264 -0
  270. package/token/repositories/token-repository.js +219 -0
  271. package/types/associations/index.d.ts +0 -17
  272. package/types/core/index.d.ts +12 -4
  273. package/types/database/index.d.ts +10 -2
  274. package/types/encrypt/index.d.ts +5 -3
  275. package/types/integrations/index.d.ts +3 -8
  276. package/types/module-plugin/index.d.ts +17 -69
  277. package/types/syncs/index.d.ts +0 -17
  278. package/user/repositories/user-repository-documentdb.js +458 -0
  279. package/user/repositories/user-repository-factory.js +52 -0
  280. package/user/repositories/user-repository-interface.js +214 -0
  281. package/user/repositories/user-repository-mongo.js +323 -0
  282. package/user/repositories/user-repository-postgres.js +377 -0
  283. package/user/tests/doubles/test-user-repository.js +72 -0
  284. package/user/use-cases/authenticate-user.js +127 -0
  285. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  286. package/user/use-cases/create-individual-user.js +61 -0
  287. package/user/use-cases/create-organization-user.js +47 -0
  288. package/user/use-cases/create-token-for-user-id.js +30 -0
  289. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  290. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  291. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  292. package/user/use-cases/login-user.js +122 -0
  293. package/user/user.js +125 -0
  294. package/utils/backend-path.js +38 -0
  295. package/utils/index.js +6 -0
  296. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  297. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  298. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  299. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  300. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  301. package/websocket/repositories/websocket-connection-repository.js +161 -0
  302. package/assertions/is-equal.js +0 -17
  303. package/associations/model.js +0 -54
  304. package/database/models/IndividualUser.js +0 -76
  305. package/database/models/OrganizationUser.js +0 -29
  306. package/database/models/State.js +0 -9
  307. package/database/models/Token.js +0 -70
  308. package/database/models/UserModel.js +0 -7
  309. package/database/models/WebsocketConnection.js +0 -49
  310. package/database/mongo.js +0 -45
  311. package/database/mongoose.js +0 -5
  312. package/encrypt/Cryptor.test.js +0 -32
  313. package/encrypt/encrypt.js +0 -132
  314. package/encrypt/encrypt.test.js +0 -1069
  315. package/encrypt/test-encrypt.js +0 -107
  316. package/errors/base-error.test.js +0 -32
  317. package/errors/fetch-error.test.js +0 -79
  318. package/errors/halt-error.test.js +0 -11
  319. package/errors/validation-errors.test.js +0 -120
  320. package/integrations/create-frigg-backend.js +0 -31
  321. package/integrations/integration-factory.js +0 -251
  322. package/integrations/integration-mapping.js +0 -43
  323. package/integrations/integration-model.js +0 -46
  324. package/integrations/integration-user.js +0 -144
  325. package/integrations/test/integration-base.test.js +0 -144
  326. package/lambda/TimeoutCatcher.test.js +0 -68
  327. package/logs/logger.test.js +0 -76
  328. package/module-plugin/auther.js +0 -350
  329. package/module-plugin/credential.js +0 -22
  330. package/module-plugin/entity-manager.js +0 -70
  331. package/module-plugin/entity.js +0 -46
  332. package/module-plugin/manager.js +0 -169
  333. package/module-plugin/module-factory.js +0 -61
  334. package/module-plugin/requester/api-key.js +0 -36
  335. package/module-plugin/requester/oauth-2.js +0 -219
  336. package/module-plugin/requester/requester.js +0 -165
  337. package/module-plugin/requester/requester.test.js +0 -28
  338. package/module-plugin/test/auther.test.js +0 -97
  339. package/syncs/model.js +0 -62
  340. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  341. /package/{module-plugin → modules}/requester/basic.js +0 -0
  342. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Admin Scripts Module
3
+ *
4
+ * Exports repository interfaces and factories for admin script management.
5
+ * Concrete implementations support MongoDB, PostgreSQL, and DocumentDB.
6
+ *
7
+ * Repository interfaces follow the Port pattern in Hexagonal Architecture:
8
+ * - Define contracts for data access
9
+ * - Enable dependency injection
10
+ * - Allow testing with mocks
11
+ * - Support multiple database implementations
12
+ *
13
+ * Authentication:
14
+ * - Uses ENV-based ADMIN_API_KEY (see handlers/middleware/admin-auth.js)
15
+ * - No database-backed API keys (simplified from original design)
16
+ */
17
+
18
+ // Repository Interfaces
19
+ const { AdminScriptExecutionRepositoryInterface } = require('./repositories/admin-script-execution-repository-interface');
20
+ const { ScriptScheduleRepositoryInterface } = require('./repositories/script-schedule-repository-interface');
21
+
22
+ // Repository Factories
23
+ const {
24
+ createAdminScriptExecutionRepository,
25
+ AdminScriptExecutionRepositoryMongo,
26
+ AdminScriptExecutionRepositoryPostgres,
27
+ AdminScriptExecutionRepositoryDocumentDB,
28
+ } = require('./repositories/admin-script-execution-repository-factory');
29
+ const {
30
+ createScriptScheduleRepository,
31
+ ScriptScheduleRepositoryMongo,
32
+ ScriptScheduleRepositoryPostgres,
33
+ ScriptScheduleRepositoryDocumentDB,
34
+ } = require('./repositories/script-schedule-repository-factory');
35
+
36
+ module.exports = {
37
+ // Repository Interfaces
38
+ AdminScriptExecutionRepositoryInterface,
39
+ ScriptScheduleRepositoryInterface,
40
+
41
+ // Repository Factories (primary exports for use cases)
42
+ createAdminScriptExecutionRepository,
43
+ createScriptScheduleRepository,
44
+
45
+ // Concrete Implementations (for testing)
46
+ AdminScriptExecutionRepositoryMongo,
47
+ AdminScriptExecutionRepositoryPostgres,
48
+ AdminScriptExecutionRepositoryDocumentDB,
49
+ ScriptScheduleRepositoryMongo,
50
+ ScriptScheduleRepositoryPostgres,
51
+ ScriptScheduleRepositoryDocumentDB,
52
+ };
@@ -0,0 +1,21 @@
1
+ const {
2
+ AdminScriptExecutionRepositoryMongo,
3
+ } = require('./admin-script-execution-repository-mongo');
4
+
5
+ /**
6
+ * DocumentDB Admin Process Repository Adapter
7
+ * Extends MongoDB implementation since DocumentDB uses the same Prisma client
8
+ *
9
+ * DocumentDB-specific characteristics:
10
+ * - Uses MongoDB-compatible API
11
+ * - Prisma client handles the connection
12
+ * - IDs are strings with ObjectId format
13
+ * - All operations identical to MongoDB implementation
14
+ */
15
+ class AdminScriptExecutionRepositoryDocumentDB extends AdminScriptExecutionRepositoryMongo {
16
+ constructor() {
17
+ super();
18
+ }
19
+ }
20
+
21
+ module.exports = { AdminScriptExecutionRepositoryDocumentDB };
@@ -0,0 +1,51 @@
1
+ const { AdminScriptExecutionRepositoryMongo } = require('./admin-script-execution-repository-mongo');
2
+ const { AdminScriptExecutionRepositoryPostgres } = require('./admin-script-execution-repository-postgres');
3
+ const {
4
+ AdminScriptExecutionRepositoryDocumentDB,
5
+ } = require('./admin-script-execution-repository-documentdb');
6
+ const config = require('../../database/config');
7
+
8
+ /**
9
+ * Admin Process Repository Factory
10
+ * Creates the appropriate repository adapter based on database type
11
+ *
12
+ * This implements the Factory pattern for Hexagonal Architecture:
13
+ * - Reads database type from app definition (backend/index.js)
14
+ * - Returns correct adapter (MongoDB, DocumentDB, or PostgreSQL)
15
+ * - Provides clear error for unsupported databases
16
+ *
17
+ * Usage:
18
+ * ```javascript
19
+ * const repository = createAdminScriptExecutionRepository();
20
+ * ```
21
+ *
22
+ * @returns {AdminScriptExecutionRepositoryInterface} Configured repository adapter
23
+ * @throws {Error} If database type is not supported
24
+ */
25
+ function createAdminScriptExecutionRepository() {
26
+ const dbType = config.DB_TYPE;
27
+
28
+ switch (dbType) {
29
+ case 'mongodb':
30
+ return new AdminScriptExecutionRepositoryMongo();
31
+
32
+ case 'postgresql':
33
+ return new AdminScriptExecutionRepositoryPostgres();
34
+
35
+ case 'documentdb':
36
+ return new AdminScriptExecutionRepositoryDocumentDB();
37
+
38
+ default:
39
+ throw new Error(
40
+ `Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
41
+ );
42
+ }
43
+ }
44
+
45
+ module.exports = {
46
+ createAdminScriptExecutionRepository,
47
+ // Export adapters for direct testing
48
+ AdminScriptExecutionRepositoryMongo,
49
+ AdminScriptExecutionRepositoryPostgres,
50
+ AdminScriptExecutionRepositoryDocumentDB,
51
+ };
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Admin Process Repository Interface
3
+ * Abstract base class defining the contract for admin process persistence adapters
4
+ *
5
+ * This follows the Port in Hexagonal Architecture:
6
+ * - Domain layer depends on this abstraction
7
+ * - Concrete adapters implement this interface
8
+ * - Use cases receive repositories via dependency injection
9
+ *
10
+ * Admin processes track administrative operations including:
11
+ * - Admin script executions
12
+ * - Database migrations
13
+ * - Scheduled maintenance tasks
14
+ *
15
+ * The AdminScriptExecution model uses a flexible JSON storage pattern:
16
+ * - context: Input parameters, trigger info, audit data, script version
17
+ * - results: Output data, logs, metrics, error details
18
+ *
19
+ * @abstract
20
+ */
21
+ class AdminScriptExecutionRepositoryInterface {
22
+ /**
23
+ * Create a new admin process record
24
+ *
25
+ * @param {Object} params - Process creation parameters
26
+ * @param {string} params.name - Name of the process (e.g., script name, migration name)
27
+ * @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
28
+ * @param {Object} [params.context] - Context data (input, trigger, audit, script version)
29
+ * @param {string} [params.context.scriptVersion] - Version of the script
30
+ * @param {string} [params.context.trigger] - Trigger type ('MANUAL', 'SCHEDULED', 'QUEUE', 'WEBHOOK')
31
+ * @param {string} [params.context.mode] - Execution mode ('sync' or 'async')
32
+ * @param {Object} [params.context.input] - Input parameters
33
+ * @param {Object} [params.context.audit] - Audit information
34
+ * @param {string} [params.context.audit.apiKeyName] - Name of API key used
35
+ * @param {string} [params.context.audit.apiKeyLast4] - Last 4 chars of API key
36
+ * @param {string} [params.context.audit.ipAddress] - IP address of requester
37
+ * @param {string|number} [params.parentExecutionId] - ID of the execution that queued this one; persisted to the parentExecutionId column (self-FK) for the parent/child hierarchy
38
+ * @returns {Promise<Object>} The created process record
39
+ * @abstract
40
+ */
41
+ async createExecution({ name, type, context, parentExecutionId }) {
42
+ throw new Error('Method createExecution must be implemented by subclass');
43
+ }
44
+
45
+ /**
46
+ * Find a process by its ID
47
+ *
48
+ * @param {string|number} id - The process ID
49
+ * @returns {Promise<Object|null>} The process record or null if not found
50
+ * @abstract
51
+ */
52
+ async findExecutionById(id) {
53
+ throw new Error(
54
+ 'Method findExecutionById must be implemented by subclass'
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Find all processes with a specific name
60
+ *
61
+ * @param {string} name - The process name to filter by
62
+ * @param {Object} [options] - Query options
63
+ * @param {number} [options.limit] - Maximum number of results
64
+ * @param {number} [options.offset] - Number of results to skip
65
+ * @param {string} [options.sortBy] - Field to sort by
66
+ * @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
67
+ * @param {string} [options.state] - Optional state filter ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
68
+ * @returns {Promise<Array>} Array of process records
69
+ * @abstract
70
+ */
71
+ async findExecutionsByName(name, options = {}) {
72
+ throw new Error(
73
+ 'Method findExecutionsByName must be implemented by subclass'
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Find all processes with a specific state
79
+ *
80
+ * @param {string} state - State to filter by ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
81
+ * @param {Object} [options] - Query options
82
+ * @param {number} [options.limit] - Maximum number of results
83
+ * @param {number} [options.offset] - Number of results to skip
84
+ * @param {string} [options.sortBy] - Field to sort by
85
+ * @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
86
+ * @returns {Promise<Array>} Array of process records
87
+ * @abstract
88
+ */
89
+ async findExecutionsByState(state, options = {}) {
90
+ throw new Error(
91
+ 'Method findExecutionsByState must be implemented by subclass'
92
+ );
93
+ }
94
+
95
+ /**
96
+ * Update the state of a process
97
+ *
98
+ * @param {string|number} id - The process ID
99
+ * @param {string} state - New state value ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
100
+ * @returns {Promise<Object>} Updated process record
101
+ * @abstract
102
+ */
103
+ async updateExecutionState(id, state) {
104
+ throw new Error(
105
+ 'Method updateExecutionState must be implemented by subclass'
106
+ );
107
+ }
108
+
109
+ /**
110
+ * Update the results of a process
111
+ * Merges new results with existing results in the results JSON field
112
+ *
113
+ * @param {string|number} id - The process ID
114
+ * @param {Object} results - Results data to merge
115
+ * @param {Object} [results.output] - Output data from the process
116
+ * @param {Object} [results.error] - Error information
117
+ * @param {string} [results.error.name] - Error name/type
118
+ * @param {string} [results.error.message] - Error message
119
+ * @param {string} [results.error.stack] - Error stack trace
120
+ * @param {Object} [results.metrics] - Performance metrics
121
+ * @param {Date} [results.metrics.startTime] - Process start time
122
+ * @param {Date} [results.metrics.endTime] - Process end time
123
+ * @param {number} [results.metrics.durationMs] - Duration in milliseconds
124
+ * @returns {Promise<Object>} Updated process record
125
+ * @abstract
126
+ */
127
+ async updateExecutionResults(id, results) {
128
+ throw new Error(
129
+ 'Method updateExecutionResults must be implemented by subclass'
130
+ );
131
+ }
132
+
133
+ /**
134
+ * Append a log entry to a process's log array in results
135
+ *
136
+ * @param {string|number} id - The process ID
137
+ * @param {Object} logEntry - Log entry to append
138
+ * @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
139
+ * @param {string} logEntry.message - Log message
140
+ * @param {Object} [logEntry.data] - Additional log data
141
+ * @param {string} logEntry.timestamp - ISO timestamp
142
+ * @returns {Promise<Object>} Updated process record
143
+ * @abstract
144
+ */
145
+ async appendExecutionLog(id, logEntry) {
146
+ throw new Error(
147
+ 'Method appendExecutionLog must be implemented by subclass'
148
+ );
149
+ }
150
+
151
+ /**
152
+ * Delete all processes older than a specific date
153
+ * Used for cleanup and retention policies
154
+ *
155
+ * @param {Date} date - Delete processes older than this date
156
+ * @returns {Promise<Object>} Deletion result with count
157
+ * @abstract
158
+ */
159
+ async deleteExecutionsOlderThan(date) {
160
+ throw new Error(
161
+ 'Method deleteExecutionsOlderThan must be implemented by subclass'
162
+ );
163
+ }
164
+ }
165
+
166
+ module.exports = { AdminScriptExecutionRepositoryInterface };
@@ -0,0 +1,228 @@
1
+ const { prisma } = require('../../database/prisma');
2
+ const {
3
+ AdminScriptExecutionRepositoryInterface,
4
+ } = require('./admin-script-execution-repository-interface');
5
+
6
+ /**
7
+ * MongoDB Admin Process Repository Adapter
8
+ * Handles admin process persistence using Prisma with MongoDB
9
+ *
10
+ * MongoDB-specific characteristics:
11
+ * - IDs are strings with @db.ObjectId
12
+ * - context and results are Json objects
13
+ * - Stores logs in results.logs array
14
+ */
15
+ class AdminScriptExecutionRepositoryMongo extends AdminScriptExecutionRepositoryInterface {
16
+ constructor() {
17
+ super();
18
+ this.prisma = prisma;
19
+ }
20
+
21
+ /**
22
+ * Create a new admin process record
23
+ *
24
+ * @param {Object} params - Process creation parameters
25
+ * @param {string} params.name - Name of the process
26
+ * @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
27
+ * @param {Object} [params.context] - Context data
28
+ * @returns {Promise<Object>} The created process record
29
+ */
30
+ async createExecution({ name, type, context = {}, parentExecutionId }) {
31
+ const data = {
32
+ name,
33
+ type,
34
+ context,
35
+ results: { logs: [] },
36
+ ...(parentExecutionId != null && { parentExecutionId }),
37
+ };
38
+
39
+ const process = await this.prisma.adminScriptExecution.create({
40
+ data,
41
+ });
42
+
43
+ return process;
44
+ }
45
+
46
+ /**
47
+ * Find a process by its ID
48
+ *
49
+ * @param {string} id - The process ID
50
+ * @returns {Promise<Object|null>} The process record or null if not found
51
+ */
52
+ async findExecutionById(id) {
53
+ const process = await this.prisma.adminScriptExecution.findUnique({
54
+ where: { id },
55
+ });
56
+
57
+ return process;
58
+ }
59
+
60
+ /**
61
+ * Find all processes with a specific name
62
+ *
63
+ * @param {string} name - The process name to filter by
64
+ * @param {Object} [options] - Query options
65
+ * @param {number} [options.limit] - Maximum number of results
66
+ * @param {number} [options.offset] - Number of results to skip
67
+ * @param {string} [options.sortBy] - Field to sort by
68
+ * @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
69
+ * @returns {Promise<Array>} Array of process records
70
+ */
71
+ async findExecutionsByName(name, options = {}) {
72
+ const {
73
+ limit,
74
+ offset,
75
+ sortBy = 'createdAt',
76
+ sortOrder = 'desc',
77
+ state,
78
+ } = options;
79
+
80
+ const where = { name };
81
+ if (state) where.state = state;
82
+
83
+ const processes = await this.prisma.adminScriptExecution.findMany({
84
+ where,
85
+ orderBy: { [sortBy]: sortOrder },
86
+ take: limit,
87
+ skip: offset,
88
+ });
89
+
90
+ return processes;
91
+ }
92
+
93
+ /**
94
+ * Find all processes with a specific state
95
+ *
96
+ * @param {string} state - State to filter by
97
+ * @param {Object} [options] - Query options
98
+ * @param {number} [options.limit] - Maximum number of results
99
+ * @param {number} [options.offset] - Number of results to skip
100
+ * @param {string} [options.sortBy] - Field to sort by
101
+ * @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
102
+ * @returns {Promise<Array>} Array of process records
103
+ */
104
+ async findExecutionsByState(state, options = {}) {
105
+ const {
106
+ limit,
107
+ offset,
108
+ sortBy = 'createdAt',
109
+ sortOrder = 'desc',
110
+ } = options;
111
+
112
+ const processes = await this.prisma.adminScriptExecution.findMany({
113
+ where: { state },
114
+ orderBy: { [sortBy]: sortOrder },
115
+ take: limit,
116
+ skip: offset,
117
+ });
118
+
119
+ return processes;
120
+ }
121
+
122
+ /**
123
+ * Update the state of a process
124
+ *
125
+ * @param {string} id - The process ID
126
+ * @param {string} state - New state value
127
+ * @returns {Promise<Object>} Updated process record
128
+ */
129
+ async updateExecutionState(id, state) {
130
+ const process = await this.prisma.adminScriptExecution.update({
131
+ where: { id },
132
+ data: { state },
133
+ });
134
+
135
+ return process;
136
+ }
137
+
138
+ /**
139
+ * Update the results of a process
140
+ * Merges new results with existing results
141
+ *
142
+ * @param {string} id - The process ID
143
+ * @param {Object} results - Results data to merge
144
+ * @returns {Promise<Object>} Updated process record
145
+ */
146
+ async updateExecutionResults(id, results) {
147
+ // Get current process to merge results
148
+ const currentProcess = await this.prisma.adminScriptExecution.findUnique({
149
+ where: { id },
150
+ });
151
+
152
+ if (!currentProcess) {
153
+ throw new Error(`AdminScriptExecution ${id} not found`);
154
+ }
155
+
156
+ // Merge new results with existing results
157
+ const mergedResults = {
158
+ ...(currentProcess.results || {}),
159
+ ...results,
160
+ };
161
+
162
+ const process = await this.prisma.adminScriptExecution.update({
163
+ where: { id },
164
+ data: { results: mergedResults },
165
+ });
166
+
167
+ return process;
168
+ }
169
+
170
+ /**
171
+ * Append a log entry to a process's log array in results
172
+ *
173
+ * @param {string} id - The process ID
174
+ * @param {Object} logEntry - Log entry to append
175
+ * @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
176
+ * @param {string} logEntry.message - Log message
177
+ * @param {Object} [logEntry.data] - Additional log data
178
+ * @param {string} logEntry.timestamp - ISO timestamp
179
+ * @returns {Promise<Object>} Updated process record
180
+ */
181
+ async appendExecutionLog(id, logEntry) {
182
+ // Get current process
183
+ const process = await this.prisma.adminScriptExecution.findUnique({
184
+ where: { id },
185
+ });
186
+
187
+ if (!process) {
188
+ throw new Error(`AdminScriptExecution ${id} not found`);
189
+ }
190
+
191
+ // Get current results and logs
192
+ const results = process.results || {};
193
+ const logs = Array.isArray(results.logs) ? [...results.logs] : [];
194
+ logs.push(logEntry);
195
+
196
+ // Update with new logs array in results
197
+ const updated = await this.prisma.adminScriptExecution.update({
198
+ where: { id },
199
+ data: { results: { ...results, logs } },
200
+ });
201
+
202
+ return updated;
203
+ }
204
+
205
+ /**
206
+ * Delete all processes older than a specific date
207
+ * Used for cleanup and retention policies
208
+ *
209
+ * @param {Date} date - Delete processes older than this date
210
+ * @returns {Promise<Object>} Deletion result with count
211
+ */
212
+ async deleteExecutionsOlderThan(date) {
213
+ const result = await this.prisma.adminScriptExecution.deleteMany({
214
+ where: {
215
+ createdAt: {
216
+ lt: date,
217
+ },
218
+ },
219
+ });
220
+
221
+ return {
222
+ acknowledged: true,
223
+ deletedCount: result.count,
224
+ };
225
+ }
226
+ }
227
+
228
+ module.exports = { AdminScriptExecutionRepositoryMongo };