@friggframework/core 2.0.0-next.10 → 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 (344) 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 +3 -3
  129. package/handlers/backend-utils.js +271 -42
  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 +4 -15
  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 +85 -10
  139. package/handlers/routers/integration-webhook-routers.js +67 -0
  140. package/handlers/routers/reporting.js +9 -0
  141. package/handlers/routers/user.js +27 -5
  142. package/handlers/routers/websocket.js +5 -3
  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 +13 -7
  148. package/index.js +91 -46
  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 +398 -180
  160. package/integrations/options.js +1 -1
  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/handlers/routers/middleware/loadUser.js +0 -15
  321. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  322. package/integrations/create-frigg-backend.js +0 -31
  323. package/integrations/integration-factory.js +0 -251
  324. package/integrations/integration-mapping.js +0 -43
  325. package/integrations/integration-model.js +0 -46
  326. package/integrations/integration-user.js +0 -144
  327. package/integrations/test/integration-base.test.js +0 -144
  328. package/lambda/TimeoutCatcher.test.js +0 -68
  329. package/logs/logger.test.js +0 -76
  330. package/module-plugin/auther.js +0 -393
  331. package/module-plugin/credential.js +0 -22
  332. package/module-plugin/entity-manager.js +0 -70
  333. package/module-plugin/entity.js +0 -46
  334. package/module-plugin/manager.js +0 -169
  335. package/module-plugin/module-factory.js +0 -61
  336. package/module-plugin/requester/api-key.js +0 -36
  337. package/module-plugin/requester/oauth-2.js +0 -219
  338. package/module-plugin/requester/requester.js +0 -165
  339. package/module-plugin/requester/requester.test.js +0 -28
  340. package/module-plugin/test/auther.test.js +0 -97
  341. package/syncs/model.js +0 -62
  342. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  343. /package/{module-plugin → modules}/requester/basic.js +0 -0
  344. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,161 @@
1
+ const { prisma } = require('../../database/prisma');
2
+ const {
3
+ ApiGatewayManagementApiClient,
4
+ PostToConnectionCommand,
5
+ } = require('@aws-sdk/client-apigatewaymanagementapi');
6
+ const {
7
+ WebsocketConnectionRepositoryInterface,
8
+ } = require('./websocket-connection-repository-interface');
9
+
10
+ /**
11
+ * Prisma-based WebSocket Connection Repository
12
+ * Handles persistence of active WebSocket connections
13
+ *
14
+ * Works identically for both MongoDB and PostgreSQL:
15
+ * - MongoDB: String IDs with @db.ObjectId
16
+ * - PostgreSQL: Integer IDs with auto-increment
17
+ * - Both use same query patterns (no many-to-many differences)
18
+ *
19
+ * Migration from Mongoose:
20
+ * - Constructor injection of Prisma client
21
+ * - Static method getActiveConnections() → Instance method
22
+ * - AWS API Gateway Management API integration preserved
23
+ */
24
+ class WebsocketConnectionRepository extends WebsocketConnectionRepositoryInterface {
25
+ constructor(prismaClient = prisma) {
26
+ super();
27
+ this.prisma = prismaClient; // Allow injection for testing
28
+ }
29
+
30
+ /**
31
+ * Create a new WebSocket connection record
32
+ * Replaces: WebsocketConnection.create({ connectionId })
33
+ *
34
+ * @param {string} connectionId - The WebSocket connection ID
35
+ * @returns {Promise<Object>} The created connection record
36
+ */
37
+ async createConnection(connectionId) {
38
+ return await this.prisma.websocketConnection.create({
39
+ data: { connectionId },
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Delete a WebSocket connection record
45
+ * Replaces: WebsocketConnection.deleteOne({ connectionId })
46
+ *
47
+ * @param {string} connectionId - The WebSocket connection ID to delete
48
+ * @returns {Promise<Object>} The deletion result
49
+ */
50
+ async deleteConnection(connectionId) {
51
+ try {
52
+ await this.prisma.websocketConnection.delete({
53
+ where: { connectionId },
54
+ });
55
+ return { acknowledged: true, deletedCount: 1 };
56
+ } catch (error) {
57
+ if (error.code === 'P2025') {
58
+ // Record not found
59
+ return { acknowledged: true, deletedCount: 0 };
60
+ }
61
+ throw error;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get all active WebSocket connections with send capability
67
+ * Replaces: WebsocketConnection.getActiveConnections()
68
+ *
69
+ * @returns {Promise<Array>} Array of active connection objects with send capability
70
+ */
71
+ async getActiveConnections() {
72
+ try {
73
+ // Return empty array if websockets are not configured
74
+ if (!process.env.WEBSOCKET_API_ENDPOINT) {
75
+ return [];
76
+ }
77
+
78
+ const connections = await this.prisma.websocketConnection.findMany({
79
+ select: { connectionId: true },
80
+ });
81
+
82
+ return connections.map((conn) => ({
83
+ connectionId: conn.connectionId,
84
+ send: async (data) => {
85
+ const apigwManagementApi = new ApiGatewayManagementApiClient({
86
+ endpoint: process.env.WEBSOCKET_API_ENDPOINT,
87
+ });
88
+
89
+ try {
90
+ const command = new PostToConnectionCommand({
91
+ ConnectionId: conn.connectionId,
92
+ Data: JSON.stringify(data),
93
+ });
94
+ await apigwManagementApi.send(command);
95
+ } catch (error) {
96
+ if (error.statusCode === 410 || error.$metadata?.httpStatusCode === 410) {
97
+ console.log(
98
+ `Stale connection ${conn.connectionId}`
99
+ );
100
+ // Delete stale connection
101
+ await this.prisma.websocketConnection.deleteMany({
102
+ where: { connectionId: conn.connectionId },
103
+ });
104
+ } else {
105
+ throw error;
106
+ }
107
+ }
108
+ },
109
+ }));
110
+ } catch (error) {
111
+ console.error('Error getting active connections:', error);
112
+ throw error;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Find a connection by ID
118
+ * Replaces: WebsocketConnection.findOne({ connectionId })
119
+ *
120
+ * @param {string} connectionId - The WebSocket connection ID
121
+ * @returns {Promise<Object|null>} The connection record or null
122
+ */
123
+ async findConnection(connectionId) {
124
+ return await this.prisma.websocketConnection.findFirst({
125
+ where: { connectionId },
126
+ });
127
+ }
128
+
129
+ /**
130
+ * Find connection by internal ID
131
+ * @param {string} id - The internal connection ID
132
+ * @returns {Promise<Object|null>} The connection record or null
133
+ */
134
+ async findConnectionById(id) {
135
+ return await this.prisma.websocketConnection.findUnique({
136
+ where: { id },
137
+ });
138
+ }
139
+
140
+ /**
141
+ * Get all connections
142
+ * @returns {Promise<Array>} Array of all connection records
143
+ */
144
+ async getAllConnections() {
145
+ return await this.prisma.websocketConnection.findMany();
146
+ }
147
+
148
+ /**
149
+ * Delete all connections
150
+ * @returns {Promise<Object>} The deletion result
151
+ */
152
+ async deleteAllConnections() {
153
+ const result = await this.prisma.websocketConnection.deleteMany();
154
+ return {
155
+ acknowledged: true,
156
+ deletedCount: result.count,
157
+ };
158
+ }
159
+ }
160
+
161
+ module.exports = { WebsocketConnectionRepository };
@@ -1,17 +0,0 @@
1
- const expectShallowEqualDbObject = (modelObject, compareObject) => {
2
- for (const key in compareObject) {
3
- let objVal = modelObject[key];
4
-
5
- if (objVal instanceof Date) {
6
- objVal = objVal.toISOString();
7
- } else if (objVal instanceof mongoose.Types.ObjectId) {
8
- objVal = objVal._id.toString();
9
- }
10
-
11
- expect(compareObject[key]).toBe(objVal);
12
- }
13
- };
14
-
15
- // TODO not sure how much this is needed, but could rewrite with _.isEqualWith for deep equality with custom checks.
16
-
17
- module.exports = { expectShallowEqualDbObject };
@@ -1,54 +0,0 @@
1
- const mongoose = require("mongoose");
2
-
3
- const schema = new mongoose.Schema({
4
- integration: {
5
- type: mongoose.Schema.Types.ObjectId,
6
- ref: "Integration",
7
- required: true,
8
- },
9
- name: { type: String, required: true },
10
- type: {
11
- type: String,
12
- enum: ["ONE_TO_MANY", "ONE_TO_ONE", "MANY_TO_ONE"],
13
- required: true,
14
- },
15
- primaryObject: { type: String, required: true },
16
- objects: [
17
- {
18
- entity: {
19
- type: mongoose.Schema.Types.ObjectId,
20
- ref: "Entity",
21
- required: true,
22
- },
23
- objectType: { type: String, required: true },
24
- objId: { type: String, required: true },
25
- metadata: { type: Object, required: false },
26
- },
27
- ],
28
- });
29
-
30
- schema.statics({
31
- addAssociation: async function (id, object) {
32
- return this.update({ _id: id }, { $push: { objects: object } });
33
- },
34
- findAssociation: async function (name, dataIdentifierHash) {
35
- const syncList = await this.list({
36
- name: name,
37
- "dataIdentifiers.hash": dataIdentifierHash,
38
- });
39
-
40
- if (syncList.length === 1) {
41
- return syncList[0];
42
- } else if (syncList.length === 0) {
43
- return null;
44
- } else {
45
- throw new Error(
46
- `there are multiple sync objects with the name ${name}, for entities [${entities}]`
47
- );
48
- }
49
- },
50
- });
51
-
52
- const Association =
53
- mongoose.models.Association || mongoose.model("Association", schema);
54
- module.exports = { Association };
@@ -1,76 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
- const bcrypt = require('bcryptjs');
3
- const { UserModel: Parent } = require('./UserModel');
4
-
5
- const collectionName = 'IndividualUser';
6
-
7
- const schema = new mongoose.Schema({
8
- email: { type: String },
9
- username: { type: String, unique: true },
10
- hashword: { type: String },
11
- appUserId: { type: String },
12
- organizationUser: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
13
- });
14
-
15
- schema.pre('save', async function () {
16
- if (this.hashword) {
17
- this.hashword = await bcrypt.hashSync(
18
- this.hashword,
19
- parseInt(this.schema.statics.decimals)
20
- )
21
- }
22
- })
23
-
24
- schema.static({
25
- decimals: 10,
26
- update: async function (id, options) {
27
- if ('password' in options) {
28
- options.hashword = await bcrypt.hashSync(
29
- options.password,
30
- parseInt(this.decimals)
31
- );
32
- delete options.password;
33
- }
34
- return this.findOneAndUpdate(
35
- {_id: id},
36
- options,
37
- {new: true, useFindAndModify: true}
38
- );
39
- },
40
- getUserByUsername: async function (username) {
41
- let getByUser;
42
- try{
43
- getByUser = await this.find({username});
44
- } catch (e) {
45
- console.log('oops')
46
- }
47
-
48
- if (getByUser.length > 1) {
49
- throw new Error(
50
- 'Unique username or email? Please reach out to our developers'
51
- );
52
- }
53
-
54
- if (getByUser.length === 1) {
55
- return getByUser[0];
56
- }
57
- },
58
- getUserByAppUserId: async function (appUserId) {
59
- const getByUser = await this.find({ appUserId });
60
-
61
- if (getByUser.length > 1) {
62
- throw new Error(
63
- 'Supposedly using a unique appUserId? Please reach out to our developers'
64
- );
65
- }
66
-
67
-
68
- if (getByUser.length === 1) {
69
- return getByUser[0];
70
- }
71
- }
72
- })
73
-
74
- const IndividualUser = Parent.discriminators?.IndividualUser || Parent.discriminator(collectionName, schema);
75
-
76
- module.exports = {IndividualUser};
@@ -1,29 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
- const { UserModel: Parent } = require('./UserModel');
3
-
4
- const collectionName = 'OrganizationUser';
5
-
6
- const schema = new mongoose.Schema({
7
- appOrgId: { type: String, required: true, unique: true },
8
- name: { type: String },
9
- });
10
-
11
- schema.static({
12
- getUserByAppOrgId: async function (appOrgId) {
13
- const getByUser = await this.find({ appOrgId });
14
-
15
- if (getByUser.length > 1) {
16
- throw new Error(
17
- 'Supposedly using a unique appOrgId? Please reach out to our developers'
18
- );
19
- }
20
-
21
- if (getByUser.length === 1) {
22
- return getByUser[0];
23
- }
24
- }
25
- })
26
-
27
- const OrganizationUser = Parent.discriminators?.OrganizationUser || Parent.discriminator(collectionName, schema);
28
-
29
- module.exports = {OrganizationUser};
@@ -1,9 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
-
3
- const schema = new mongoose.Schema({
4
- state: { type: mongoose.Schema.Types.Mixed }
5
- });
6
-
7
- const State = mongoose.models.State || mongoose.model('State', schema);
8
-
9
- module.exports = { State };
@@ -1,70 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
- const bcrypt = require('bcryptjs');
3
-
4
- const collectionName = 'Token';
5
- const decimals = 10;
6
-
7
- const schema = new mongoose.Schema({
8
- token: { type: String, required: true },
9
- created: { type: Date, default: Date.now },
10
- expires: { type: Date },
11
- user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
12
- });
13
-
14
- schema.static({
15
- createTokenWithExpire: async function (userId, rawToken, minutes) {
16
- // Create user token
17
- let tokenHash = await bcrypt.hashSync(rawToken, parseInt(decimals));
18
-
19
- let session = {
20
- token: tokenHash,
21
- expires: new Date(Date.now() + minutes * 60000).toISOString(),
22
- user: userId,
23
- };
24
-
25
- return this.create(session);
26
- },
27
- // Takes in a token object and that has been created in the database and the raw token value.
28
- // Returns a json of just the token and id to return to the browser
29
- createJSONToken: function (token, rawToken) {
30
- let returnArr = {
31
- id: token.id,
32
- token: rawToken,
33
- };
34
- return JSON.stringify(returnArr);
35
- },
36
- // Takes in a token object and that has been created in the database and the raw token value.
37
- // Returns a base64 buffer of just the token and id to return to the browser
38
- createBase64BufferToken: function (token, rawToken) {
39
- let jsonVal = Token.createJSONToken(token, rawToken);
40
- return Buffer.from(jsonVal).toString('base64');
41
- },
42
- getJSONTokenFromBase64BufferToken: function (buffer) {
43
- let tokenStr = Buffer.from(buffer.trim(), 'base64').toString('ascii');
44
- return JSON.parse(tokenStr);
45
- },
46
-
47
- // Takes in a JSON Token with id and token in it and verifies the token
48
- // is valid from the database. If it is not va
49
- validateAndGetTokenFromJSONToken: async function (tokenObj) {
50
- let sessionToken = await this.findById(tokenObj.id);
51
- if (sessionToken) {
52
- if (
53
- !(await bcrypt.compareSync(tokenObj.token, sessionToken.token))
54
- ) {
55
- throw new Error('Invalid Token: Token does not match');
56
- }
57
- if (new Date(sessionToken.expires) < new Date()) {
58
- throw new Error('Invalid Token: Token is expired');
59
- }
60
-
61
- return sessionToken;
62
- } else {
63
- throw new Error('Invalid Token: Token does not exist');
64
- }
65
- }
66
- })
67
-
68
- const Token = mongoose.models.Token || mongoose.model(collectionName, schema);
69
-
70
- module.exports = { Token };
@@ -1,7 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
-
3
- const schema = new mongoose.Schema({}, {timestamps: true})
4
-
5
- const UserModel = mongoose.models.User || mongoose.model('User',schema)
6
-
7
- module.exports = { UserModel: UserModel };
@@ -1,49 +0,0 @@
1
- const { mongoose } = require('../mongoose');
2
- const AWS = require('aws-sdk');
3
-
4
- const schema = new mongoose.Schema({
5
- connectionId: { type: mongoose.Schema.Types.String },
6
- });
7
-
8
- // Add a static method to get active connections
9
- schema.statics.getActiveConnections = async function () {
10
- try {
11
- const connections = await this.find({}, 'connectionId');
12
- return connections.map((conn) => ({
13
- connectionId: conn.connectionId,
14
- send: async (data) => {
15
- const apigwManagementApi = new AWS.ApiGatewayManagementApi({
16
- apiVersion: '2018-11-29',
17
- endpoint: process.env.WEBSOCKET_API_ENDPOINT,
18
- });
19
-
20
- try {
21
- await apigwManagementApi
22
- .postToConnection({
23
- ConnectionId: conn.connectionId,
24
- Data: JSON.stringify(data),
25
- })
26
- .promise();
27
- } catch (error) {
28
- if (error.statusCode === 410) {
29
- console.log(`Stale connection ${conn.connectionId}`);
30
- await this.deleteOne({
31
- connectionId: conn.connectionId,
32
- });
33
- } else {
34
- throw error;
35
- }
36
- }
37
- },
38
- }));
39
- } catch (error) {
40
- console.error('Error getting active connections:', error);
41
- throw error;
42
- }
43
- };
44
-
45
- const WebsocketConnection =
46
- mongoose.models.WebsocketConnection ||
47
- mongoose.model('WebsocketConnection', schema);
48
-
49
- module.exports = { WebsocketConnection };
package/database/mongo.js DELETED
@@ -1,45 +0,0 @@
1
- // Best Practices Connecting from AWS Lambda:
2
- // https://dev.to/adnanrahic/building-a-serverless-rest-api-with-nodejs-and-mongodb-43db
3
- // https://mongoosejs.com/docs/lambda.html
4
- // https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs
5
- const { Encrypt } = require('../encrypt');
6
- const { mongoose } = require('./mongoose');
7
- const { debug, flushDebugLog } = require('../logs');
8
-
9
- mongoose.plugin(Encrypt);
10
- mongoose.set('applyPluginsToDiscriminators', true); // Needed for LHEncrypt
11
-
12
- // Buffering means mongoose will queue up operations if it gets
13
- // With serverless, better to fail fast if not connected.
14
- // disconnected from MongoDB and send them when it reconnects.
15
- const mongoConfig = {
16
- useNewUrlParser: true,
17
- bufferCommands: false, // Disable mongoose buffering
18
- autoCreate: false, // Disable because auto creation does not work without buffering
19
- useUnifiedTopology: true,
20
- serverSelectionTimeoutMS: 5000,
21
- };
22
-
23
- const checkIsConnected = () => mongoose.connection?.readyState > 0;
24
-
25
- const connectToDatabase = async () => {
26
- if (checkIsConnected()) {
27
- debug('=> using existing database connection');
28
- return;
29
- }
30
-
31
- debug('=> using new database connection');
32
- await mongoose.connect(process.env.MONGO_URI, mongoConfig);
33
- debug('Connection state:', mongoose.STATES[mongoose.connection.readyState]);
34
- mongoose.connection.on('error', (error) => flushDebugLog(error));
35
- };
36
-
37
- const disconnectFromDatabase = async () => mongoose.disconnect();
38
-
39
- const createObjectId = () => new mongoose.Types.ObjectId();
40
-
41
- module.exports = {
42
- connectToDatabase,
43
- disconnectFromDatabase,
44
- createObjectId,
45
- };
@@ -1,5 +0,0 @@
1
- const mongoose = require('mongoose');
2
- mongoose.set('strictQuery', false);
3
- module.exports = {
4
- mongoose
5
- }
@@ -1,32 +0,0 @@
1
- const { Cryptor } = require('./Cryptor');
2
-
3
- describe('Cryptor', () => {
4
- describe('Permutations', () => {
5
- it('calculates permutations correctly', async () => {
6
- // Given a nested field, we want all possible paths that could access it.
7
- const cryptor = new Cryptor({ fields: ['a.b.c.d', 'e'] });
8
- expect(cryptor.permutationsByField).toEqual({
9
- 'a.b.c.d': [
10
- ['a', 'b', 'c', 'd'],
11
- ['a', 'b', 'c.d'],
12
- ['a', 'b.c', 'd'],
13
- ['a', 'b.c.d'],
14
- ['a.b', 'c', 'd'],
15
- ['a.b', 'c.d'],
16
- ['a.b.c', 'd'],
17
- ['a.b.c.d'],
18
- ],
19
- e: [['e']],
20
- });
21
- });
22
- });
23
-
24
- describe('Keys', () => {
25
- it('raises error on missing environment', () => {
26
- const cryptor = new Cryptor({ fields: ['a.b.c.d', 'e'] });
27
- expect(cryptor.getKeyFromEnvironment).toThrow(
28
- 'No encryption key found with ID "undefined"'
29
- );
30
- });
31
- });
32
- });