@friggframework/core 2.0.0-next.6 → 2.0.0-next.60

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 (285) hide show
  1. package/CLAUDE.md +694 -0
  2. package/README.md +959 -50
  3. package/application/commands/README.md +451 -0
  4. package/application/commands/credential-commands.js +245 -0
  5. package/application/commands/entity-commands.js +336 -0
  6. package/application/commands/integration-commands.js +210 -0
  7. package/application/commands/user-commands.js +283 -0
  8. package/application/index.js +69 -0
  9. package/core/CLAUDE.md +690 -0
  10. package/core/Worker.js +8 -21
  11. package/core/create-handler.js +14 -7
  12. package/credential/repositories/credential-repository-documentdb.js +304 -0
  13. package/credential/repositories/credential-repository-factory.js +54 -0
  14. package/credential/repositories/credential-repository-interface.js +98 -0
  15. package/credential/repositories/credential-repository-mongo.js +269 -0
  16. package/credential/repositories/credential-repository-postgres.js +291 -0
  17. package/credential/repositories/credential-repository.js +302 -0
  18. package/credential/use-cases/get-credential-for-user.js +25 -0
  19. package/credential/use-cases/update-authentication-status.js +15 -0
  20. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  21. package/database/adapters/lambda-invoker.js +97 -0
  22. package/database/config.js +154 -0
  23. package/database/documentdb-encryption-service.js +330 -0
  24. package/database/documentdb-utils.js +136 -0
  25. package/database/encryption/README.md +839 -0
  26. package/database/encryption/documentdb-encryption-service.md +3575 -0
  27. package/database/encryption/encryption-schema-registry.js +268 -0
  28. package/database/encryption/field-encryption-service.js +226 -0
  29. package/database/encryption/logger.js +79 -0
  30. package/database/encryption/prisma-encryption-extension.js +222 -0
  31. package/database/index.js +61 -21
  32. package/database/models/WebsocketConnection.js +16 -10
  33. package/database/models/readme.md +1 -0
  34. package/database/prisma.js +182 -0
  35. package/database/repositories/health-check-repository-documentdb.js +134 -0
  36. package/database/repositories/health-check-repository-factory.js +48 -0
  37. package/database/repositories/health-check-repository-interface.js +82 -0
  38. package/database/repositories/health-check-repository-mongodb.js +89 -0
  39. package/database/repositories/health-check-repository-postgres.js +82 -0
  40. package/database/repositories/health-check-repository.js +108 -0
  41. package/database/repositories/migration-status-repository-s3.js +137 -0
  42. package/database/use-cases/check-database-health-use-case.js +29 -0
  43. package/database/use-cases/check-database-state-use-case.js +81 -0
  44. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  45. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  46. package/database/use-cases/get-migration-status-use-case.js +93 -0
  47. package/database/use-cases/run-database-migration-use-case.js +139 -0
  48. package/database/use-cases/test-encryption-use-case.js +253 -0
  49. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  50. package/database/utils/mongodb-collection-utils.js +91 -0
  51. package/database/utils/mongodb-schema-init.js +106 -0
  52. package/database/utils/prisma-runner.js +477 -0
  53. package/database/utils/prisma-schema-parser.js +182 -0
  54. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  55. package/encrypt/Cryptor.js +34 -168
  56. package/encrypt/index.js +1 -2
  57. package/encrypt/test-encrypt.js +0 -2
  58. package/errors/client-safe-error.js +26 -0
  59. package/errors/fetch-error.js +2 -1
  60. package/errors/index.js +2 -0
  61. package/generated/prisma-mongodb/client.d.ts +1 -0
  62. package/generated/prisma-mongodb/client.js +4 -0
  63. package/generated/prisma-mongodb/default.d.ts +1 -0
  64. package/generated/prisma-mongodb/default.js +4 -0
  65. package/generated/prisma-mongodb/edge.d.ts +1 -0
  66. package/generated/prisma-mongodb/edge.js +334 -0
  67. package/generated/prisma-mongodb/index-browser.js +316 -0
  68. package/generated/prisma-mongodb/index.d.ts +22903 -0
  69. package/generated/prisma-mongodb/index.js +359 -0
  70. package/generated/prisma-mongodb/package.json +183 -0
  71. package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
  72. package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
  73. package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
  74. package/generated/prisma-mongodb/runtime/binary.js +289 -0
  75. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  76. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  77. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  78. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  79. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  80. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  81. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  82. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  83. package/generated/prisma-mongodb/schema.prisma +360 -0
  84. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  85. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  86. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  87. package/generated/prisma-mongodb/wasm.js +341 -0
  88. package/generated/prisma-postgresql/client.d.ts +1 -0
  89. package/generated/prisma-postgresql/client.js +4 -0
  90. package/generated/prisma-postgresql/default.d.ts +1 -0
  91. package/generated/prisma-postgresql/default.js +4 -0
  92. package/generated/prisma-postgresql/edge.d.ts +1 -0
  93. package/generated/prisma-postgresql/edge.js +356 -0
  94. package/generated/prisma-postgresql/index-browser.js +338 -0
  95. package/generated/prisma-postgresql/index.d.ts +25077 -0
  96. package/generated/prisma-postgresql/index.js +381 -0
  97. package/generated/prisma-postgresql/package.json +183 -0
  98. package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
  99. package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
  100. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  101. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  102. package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
  103. package/generated/prisma-postgresql/runtime/binary.js +289 -0
  104. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  105. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  106. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  107. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  108. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  109. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  110. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  111. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  112. package/generated/prisma-postgresql/schema.prisma +343 -0
  113. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  114. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  115. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  116. package/generated/prisma-postgresql/wasm.js +363 -0
  117. package/handlers/WEBHOOKS.md +653 -0
  118. package/handlers/app-definition-loader.js +38 -0
  119. package/handlers/app-handler-helpers.js +56 -0
  120. package/handlers/backend-utils.js +186 -0
  121. package/handlers/database-migration-handler.js +227 -0
  122. package/handlers/integration-event-dispatcher.js +54 -0
  123. package/handlers/routers/HEALTHCHECK.md +342 -0
  124. package/handlers/routers/auth.js +15 -0
  125. package/handlers/routers/db-migration.handler.js +29 -0
  126. package/handlers/routers/db-migration.js +326 -0
  127. package/handlers/routers/health.js +516 -0
  128. package/handlers/routers/integration-defined-routers.js +45 -0
  129. package/handlers/routers/integration-webhook-routers.js +67 -0
  130. package/handlers/routers/user.js +63 -0
  131. package/handlers/routers/websocket.js +57 -0
  132. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  133. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  134. package/handlers/workers/db-migration.js +352 -0
  135. package/handlers/workers/integration-defined-workers.js +27 -0
  136. package/index.js +77 -22
  137. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  138. package/integrations/index.js +12 -10
  139. package/integrations/integration-base.js +326 -55
  140. package/integrations/integration-router.js +374 -179
  141. package/integrations/options.js +1 -1
  142. package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
  143. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  144. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  145. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  146. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  147. package/integrations/repositories/integration-mapping-repository.js +156 -0
  148. package/integrations/repositories/integration-repository-documentdb.js +210 -0
  149. package/integrations/repositories/integration-repository-factory.js +51 -0
  150. package/integrations/repositories/integration-repository-interface.js +127 -0
  151. package/integrations/repositories/integration-repository-mongo.js +303 -0
  152. package/integrations/repositories/integration-repository-postgres.js +352 -0
  153. package/integrations/repositories/process-repository-documentdb.js +243 -0
  154. package/integrations/repositories/process-repository-factory.js +53 -0
  155. package/integrations/repositories/process-repository-interface.js +90 -0
  156. package/integrations/repositories/process-repository-mongo.js +190 -0
  157. package/integrations/repositories/process-repository-postgres.js +217 -0
  158. package/integrations/tests/doubles/dummy-integration-class.js +83 -0
  159. package/integrations/tests/doubles/test-integration-repository.js +99 -0
  160. package/integrations/use-cases/create-integration.js +83 -0
  161. package/integrations/use-cases/create-process.js +128 -0
  162. package/integrations/use-cases/delete-integration-for-user.js +101 -0
  163. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
  164. package/integrations/use-cases/get-integration-for-user.js +78 -0
  165. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  166. package/integrations/use-cases/get-integration-instance.js +83 -0
  167. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  168. package/integrations/use-cases/get-possible-integrations.js +27 -0
  169. package/integrations/use-cases/get-process.js +87 -0
  170. package/integrations/use-cases/index.js +19 -0
  171. package/integrations/use-cases/load-integration-context.js +71 -0
  172. package/integrations/use-cases/update-integration-messages.js +44 -0
  173. package/integrations/use-cases/update-integration-status.js +32 -0
  174. package/integrations/use-cases/update-integration.js +93 -0
  175. package/integrations/use-cases/update-process-metrics.js +201 -0
  176. package/integrations/use-cases/update-process-state.js +119 -0
  177. package/integrations/utils/map-integration-dto.js +37 -0
  178. package/jest-global-setup-noop.js +3 -0
  179. package/jest-global-teardown-noop.js +3 -0
  180. package/logs/logger.js +0 -4
  181. package/{module-plugin → modules}/entity.js +1 -1
  182. package/{module-plugin → modules}/index.js +0 -8
  183. package/modules/module-factory.js +56 -0
  184. package/modules/module.js +221 -0
  185. package/modules/repositories/module-repository-documentdb.js +307 -0
  186. package/modules/repositories/module-repository-factory.js +40 -0
  187. package/modules/repositories/module-repository-interface.js +129 -0
  188. package/modules/repositories/module-repository-mongo.js +377 -0
  189. package/modules/repositories/module-repository-postgres.js +426 -0
  190. package/modules/repositories/module-repository.js +316 -0
  191. package/modules/requester/api-key.js +52 -0
  192. package/{module-plugin → modules}/requester/requester.js +1 -0
  193. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  194. package/{module-plugin → modules}/test/mock-api/definition.js +12 -8
  195. package/modules/tests/doubles/test-module-factory.js +16 -0
  196. package/modules/tests/doubles/test-module-repository.js +39 -0
  197. package/modules/use-cases/get-entities-for-user.js +32 -0
  198. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  199. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  200. package/modules/use-cases/get-module-instance-from-type.js +31 -0
  201. package/modules/use-cases/get-module.js +74 -0
  202. package/modules/use-cases/process-authorization-callback.js +133 -0
  203. package/modules/use-cases/refresh-entity-options.js +72 -0
  204. package/modules/use-cases/test-module-auth.js +72 -0
  205. package/modules/utils/map-module-dto.js +18 -0
  206. package/package.json +82 -50
  207. package/prisma-mongodb/schema.prisma +360 -0
  208. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  209. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  210. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  211. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  212. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  213. package/prisma-postgresql/schema.prisma +343 -0
  214. package/queues/queuer-util.js +27 -22
  215. package/syncs/manager.js +468 -443
  216. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  217. package/syncs/repositories/sync-repository-factory.js +43 -0
  218. package/syncs/repositories/sync-repository-interface.js +109 -0
  219. package/syncs/repositories/sync-repository-mongo.js +239 -0
  220. package/syncs/repositories/sync-repository-postgres.js +319 -0
  221. package/syncs/sync.js +0 -1
  222. package/token/repositories/token-repository-documentdb.js +137 -0
  223. package/token/repositories/token-repository-factory.js +40 -0
  224. package/token/repositories/token-repository-interface.js +131 -0
  225. package/token/repositories/token-repository-mongo.js +219 -0
  226. package/token/repositories/token-repository-postgres.js +264 -0
  227. package/token/repositories/token-repository.js +219 -0
  228. package/types/core/index.d.ts +2 -2
  229. package/types/integrations/index.d.ts +2 -6
  230. package/types/module-plugin/index.d.ts +5 -59
  231. package/types/syncs/index.d.ts +0 -2
  232. package/user/repositories/user-repository-documentdb.js +441 -0
  233. package/user/repositories/user-repository-factory.js +52 -0
  234. package/user/repositories/user-repository-interface.js +201 -0
  235. package/user/repositories/user-repository-mongo.js +308 -0
  236. package/user/repositories/user-repository-postgres.js +360 -0
  237. package/user/tests/doubles/test-user-repository.js +72 -0
  238. package/user/use-cases/authenticate-user.js +127 -0
  239. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  240. package/user/use-cases/create-individual-user.js +61 -0
  241. package/user/use-cases/create-organization-user.js +47 -0
  242. package/user/use-cases/create-token-for-user-id.js +30 -0
  243. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  244. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  245. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  246. package/user/use-cases/login-user.js +122 -0
  247. package/user/user.js +125 -0
  248. package/utils/backend-path.js +38 -0
  249. package/utils/index.js +6 -0
  250. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  251. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  252. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  253. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  254. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  255. package/websocket/repositories/websocket-connection-repository.js +161 -0
  256. package/database/models/State.js +0 -9
  257. package/database/models/Token.js +0 -70
  258. package/database/mongo.js +0 -45
  259. package/encrypt/Cryptor.test.js +0 -32
  260. package/encrypt/encrypt.js +0 -132
  261. package/encrypt/encrypt.test.js +0 -1069
  262. package/errors/base-error.test.js +0 -32
  263. package/errors/fetch-error.test.js +0 -79
  264. package/errors/halt-error.test.js +0 -11
  265. package/errors/validation-errors.test.js +0 -120
  266. package/integrations/create-frigg-backend.js +0 -31
  267. package/integrations/integration-factory.js +0 -251
  268. package/integrations/integration-mapping.js +0 -43
  269. package/integrations/integration-model.js +0 -46
  270. package/integrations/integration-user.js +0 -144
  271. package/integrations/test/integration-base.test.js +0 -144
  272. package/lambda/TimeoutCatcher.test.js +0 -68
  273. package/logs/logger.test.js +0 -76
  274. package/module-plugin/auther.js +0 -393
  275. package/module-plugin/credential.js +0 -22
  276. package/module-plugin/entity-manager.js +0 -70
  277. package/module-plugin/manager.js +0 -169
  278. package/module-plugin/module-factory.js +0 -61
  279. package/module-plugin/requester/api-key.js +0 -36
  280. package/module-plugin/requester/requester.test.js +0 -28
  281. package/module-plugin/test/auther.test.js +0 -97
  282. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  283. /package/{module-plugin → modules}/requester/basic.js +0 -0
  284. /package/{module-plugin → modules}/requester/oauth-2.js +0 -0
  285. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,25 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `subType` on the `Credential` table. All the data in the column will be lost.
5
+ - You are about to drop the column `subType` on the `Entity` table. All the data in the column will be lost.
6
+ - A unique constraint covering the columns `[username,appUserId]` on the table `User` will be added. If there are existing duplicate values, this will fail.
7
+
8
+ */
9
+ -- DropIndex
10
+ DROP INDEX "User_appOrgId_key";
11
+
12
+ -- DropIndex
13
+ DROP INDEX "User_email_key";
14
+
15
+ -- DropIndex
16
+ DROP INDEX "User_username_key";
17
+
18
+ -- AlterTable
19
+ ALTER TABLE "Credential" DROP COLUMN "subType";
20
+
21
+ -- AlterTable
22
+ ALTER TABLE "Entity" DROP COLUMN "subType";
23
+
24
+ -- CreateIndex
25
+ CREATE UNIQUE INDEX "User_username_appUserId_key" ON "User"("username", "appUserId");
@@ -0,0 +1,3 @@
1
+ # Please do not edit this file manually
2
+ # It should be added in your version-control system (e.g., Git)
3
+ provider = "postgresql"
@@ -0,0 +1,343 @@
1
+ // Frigg Framework - Prisma Schema (PostgreSQL)
2
+ // PostgreSQL database schema for enterprise integration platform
3
+ // Converted from MongoDB schema for relational database support
4
+
5
+ generator client {
6
+ provider = "prisma-client-js"
7
+ output = "../generated/prisma-postgresql"
8
+ binaryTargets = ["native", "rhel-openssl-3.0.x"] // native for local dev, rhel for Lambda deployment
9
+ engineType = "binary" // Use binary engines (smaller size)
10
+ }
11
+
12
+ datasource db {
13
+ provider = "postgresql"
14
+ url = env("DATABASE_URL")
15
+ }
16
+
17
+ // ============================================================================
18
+ // USER MODELS
19
+ // ============================================================================
20
+
21
+ /// User model with discriminator pattern support
22
+ /// Replaces Mongoose discriminators (IndividualUser, OrganizationUser)
23
+ model User {
24
+ id Int @id @default(autoincrement())
25
+ type UserType
26
+
27
+ // Timestamps
28
+ createdAt DateTime @default(now())
29
+ updatedAt DateTime @updatedAt
30
+
31
+ // IndividualUser fields (nullable for organizations)
32
+ email String?
33
+ username String?
34
+ hashword String? // Bcrypt hashed password (handled in application layer)
35
+ appUserId String?
36
+ organizationId Int?
37
+
38
+ // Self-referential relation for organization membership
39
+ organization User? @relation("OrgMembers", fields: [organizationId], references: [id], onDelete: NoAction, onUpdate: NoAction)
40
+ members User[] @relation("OrgMembers")
41
+
42
+ // OrganizationUser fields (nullable for individuals)
43
+ appOrgId String?
44
+ name String?
45
+
46
+ // Relations
47
+ tokens Token[]
48
+ credentials Credential[]
49
+ entities Entity[]
50
+ integrations Integration[]
51
+ processes Process[]
52
+
53
+ @@unique([username, appUserId])
54
+ @@index([type])
55
+ @@index([appUserId])
56
+ }
57
+
58
+ enum UserType {
59
+ INDIVIDUAL
60
+ ORGANIZATION
61
+ }
62
+
63
+ // ============================================================================
64
+ // AUTHENTICATION MODELS
65
+ // ============================================================================
66
+
67
+ /// Authentication tokens with expiration
68
+ /// Bcrypt hashed tokens stored (handled in application layer)
69
+ model Token {
70
+ id Int @id @default(autoincrement())
71
+ token String // Bcrypt hashed
72
+ created DateTime @default(now())
73
+ expires DateTime?
74
+ userId Int
75
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
76
+
77
+ @@index([userId])
78
+ @@index([expires])
79
+ }
80
+
81
+ // ============================================================================
82
+ // CREDENTIAL & ENTITY MODELS
83
+ // ============================================================================
84
+
85
+ /// OAuth credentials and API tokens
86
+ /// All sensitive data encrypted with KMS at rest
87
+ model Credential {
88
+ id Int @id @default(autoincrement())
89
+ userId Int?
90
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
91
+ authIsValid Boolean?
92
+ externalId String?
93
+
94
+ // Dynamic OAuth fields stored as JSON (encrypted via Prisma middleware)
95
+ // Contains: access_token, refresh_token, domain, expires_in, token_type, etc.
96
+ data Json @default("{}")
97
+
98
+ createdAt DateTime @default(now())
99
+ updatedAt DateTime @updatedAt
100
+
101
+ // Relations
102
+ entities Entity[]
103
+
104
+ @@index([userId])
105
+ @@index([externalId])
106
+ }
107
+
108
+ /// External service entities (API connections)
109
+ model Entity {
110
+ id Int @id @default(autoincrement())
111
+ credentialId Int?
112
+ credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)
113
+ userId Int?
114
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
115
+ name String?
116
+ moduleName String?
117
+ externalId String?
118
+
119
+ createdAt DateTime @default(now())
120
+ updatedAt DateTime @updatedAt
121
+
122
+ // Relations - many-to-many with implicit join tables
123
+ integrations Integration[]
124
+ syncs Sync[]
125
+
126
+ dataIdentifiers DataIdentifier[]
127
+ associationObjects AssociationObject[]
128
+
129
+ @@index([userId])
130
+ @@index([externalId])
131
+ @@index([moduleName])
132
+ @@index([credentialId])
133
+ }
134
+
135
+ // ============================================================================
136
+ // INTEGRATION MODELS
137
+ // ============================================================================
138
+
139
+ /// Main integration configuration and state
140
+ model Integration {
141
+ id Int @id @default(autoincrement())
142
+ userId Int?
143
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
144
+ status IntegrationStatus @default(ENABLED)
145
+
146
+ // Configuration and version
147
+ config Json? // Integration configuration object
148
+ version String?
149
+
150
+ // Entity references (many-to-many via implicit join table)
151
+ entities Entity[]
152
+
153
+ // Message arrays (stored as JSON)
154
+ errors Json @default("[]")
155
+ warnings Json @default("[]")
156
+ info Json @default("[]")
157
+ logs Json @default("[]")
158
+
159
+ createdAt DateTime @default(now())
160
+ updatedAt DateTime @updatedAt
161
+
162
+ // Relations
163
+ associations Association[]
164
+ syncs Sync[]
165
+ mappings IntegrationMapping[]
166
+ processes Process[]
167
+
168
+ @@index([userId])
169
+ @@index([status])
170
+ }
171
+
172
+ enum IntegrationStatus {
173
+ ENABLED
174
+ NEEDS_CONFIG
175
+ PROCESSING
176
+ DISABLED
177
+ ERROR
178
+ }
179
+
180
+ /// Integration-specific data mappings
181
+ /// All mapping data encrypted with KMS
182
+ model IntegrationMapping {
183
+ id Int @id @default(autoincrement())
184
+ integrationId Int
185
+ integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
186
+ sourceId String?
187
+
188
+ // Encrypted mapping data (handled via Prisma middleware)
189
+ mapping Json?
190
+
191
+ createdAt DateTime @default(now())
192
+ updatedAt DateTime @updatedAt
193
+
194
+ @@unique([integrationId, sourceId])
195
+ @@index([integrationId])
196
+ @@index([sourceId])
197
+ }
198
+
199
+ // ============================================================================
200
+ // SYNC MODELS
201
+ // ============================================================================
202
+
203
+ /// Bidirectional data synchronization tracking
204
+ model Sync {
205
+ id Int @id @default(autoincrement())
206
+ integrationId Int?
207
+ integration Integration? @relation(fields: [integrationId], references: [id], onDelete: Cascade)
208
+
209
+ // Entity references (many-to-many via implicit join table)
210
+ entities Entity[]
211
+
212
+ hash String
213
+ name String
214
+
215
+ // Data identifiers (extracted to separate model)
216
+ dataIdentifiers DataIdentifier[]
217
+
218
+ @@index([integrationId])
219
+ @@index([hash])
220
+ @@index([name])
221
+ }
222
+
223
+ /// Data identifier for sync operations
224
+ /// Replaces nested array structure in Mongoose
225
+ model DataIdentifier {
226
+ id Int @id @default(autoincrement())
227
+ syncId Int?
228
+ sync Sync? @relation(fields: [syncId], references: [id], onDelete: Cascade)
229
+ entityId Int
230
+ entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)
231
+
232
+ // Identifier data (can be any structure)
233
+ idData Json
234
+
235
+ hash String
236
+
237
+ @@index([syncId])
238
+ @@index([entityId])
239
+ @@index([hash])
240
+ }
241
+
242
+ // ============================================================================
243
+ // ASSOCIATION MODELS
244
+ // ============================================================================
245
+
246
+ /// Entity associations with cardinality tracking
247
+ model Association {
248
+ id Int @id @default(autoincrement())
249
+ integrationId Int
250
+ integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
251
+ name String
252
+ type AssociationType
253
+ primaryObject String
254
+
255
+ // Associated objects (extracted to separate model)
256
+ objects AssociationObject[]
257
+
258
+ @@index([integrationId])
259
+ @@index([name])
260
+ }
261
+
262
+ /// Association object entry
263
+ /// Replaces nested array structure in Mongoose
264
+ model AssociationObject {
265
+ id Int @id @default(autoincrement())
266
+ associationId Int
267
+ association Association @relation(fields: [associationId], references: [id], onDelete: Cascade)
268
+ entityId Int
269
+ entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)
270
+ objectType String
271
+ objId String
272
+ metadata Json? // Optional metadata
273
+
274
+ @@index([associationId])
275
+ @@index([entityId])
276
+ }
277
+
278
+ enum AssociationType {
279
+ ONE_TO_MANY
280
+ ONE_TO_ONE
281
+ MANY_TO_ONE
282
+ }
283
+
284
+ // ============================================================================
285
+ // PROCESS MODELS
286
+ // ============================================================================
287
+
288
+ /// Generic Process Model - tracks any long-running operation
289
+ /// Used for: CRM syncs, data migrations, bulk operations, etc.
290
+ model Process {
291
+ id Int @id @default(autoincrement())
292
+
293
+ // Core references
294
+ userId Int
295
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
296
+ integrationId Int
297
+ integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
298
+
299
+ // Process identification
300
+ name String // e.g., "zoho-crm-contact-sync", "pipedrive-lead-sync"
301
+ type String // e.g., "CRM_SYNC", "DATA_MIGRATION", "BULK_OPERATION"
302
+
303
+ // State machine
304
+ state String // Current state (integration-defined states)
305
+
306
+ // Flexible storage
307
+ context Json @default("{}") // Process-specific data (pagination, metadata, etc.)
308
+ results Json @default("{}") // Process results and metrics
309
+
310
+ // Hierarchy support - self-referential relation
311
+ parentProcessId Int?
312
+ parentProcess Process? @relation("ProcessHierarchy", fields: [parentProcessId], references: [id], onDelete: SetNull)
313
+ childProcesses Process[] @relation("ProcessHierarchy")
314
+
315
+ // Timestamps
316
+ createdAt DateTime @default(now())
317
+ updatedAt DateTime @updatedAt
318
+
319
+ @@index([userId])
320
+ @@index([integrationId])
321
+ @@index([type])
322
+ @@index([state])
323
+ @@index([name])
324
+ @@index([parentProcessId])
325
+ }
326
+
327
+ // ============================================================================
328
+ // UTILITY MODELS
329
+ // ============================================================================
330
+
331
+ /// Generic state storage
332
+ model State {
333
+ id Int @id @default(autoincrement())
334
+ state Json?
335
+ }
336
+
337
+ /// AWS API Gateway WebSocket connection tracking
338
+ model WebsocketConnection {
339
+ id Int @id @default(autoincrement())
340
+ connectionId String?
341
+
342
+ @@index([connectionId])
343
+ }
@@ -1,23 +1,33 @@
1
1
  const { v4: uuid } = require('uuid');
2
- const AWS = require('aws-sdk');
2
+ const { SQSClient, SendMessageCommand, SendMessageBatchCommand } = require('@aws-sdk/client-sqs');
3
+
3
4
  const awsConfigOptions = () => {
4
5
  const config = {};
5
6
  if (process.env.IS_OFFLINE) {
6
- console.log('Running in offline mode');
7
+ config.credentials = {
8
+ accessKeyId: 'test-aws-key',
9
+ secretAccessKey: 'test-aws-secret',
10
+ };
11
+ config.region = 'us-east-1';
7
12
  }
8
13
  if (process.env.AWS_ENDPOINT) {
9
14
  config.endpoint = process.env.AWS_ENDPOINT;
10
15
  }
11
16
  return config;
12
17
  };
13
- AWS.config.update(awsConfigOptions());
14
- const sqs = new AWS.SQS();
18
+
19
+ const sqs = new SQSClient(awsConfigOptions());
15
20
 
16
21
  const QueuerUtil = {
22
+ send: async (message, queueUrl) => {
23
+ const command = new SendMessageCommand({
24
+ MessageBody: JSON.stringify(message),
25
+ QueueUrl: queueUrl,
26
+ });
27
+ return sqs.send(command);
28
+ },
29
+
17
30
  batchSend: async (entries = [], queueUrl) => {
18
- console.log(
19
- `Enqueuing ${entries.length} entries on SQS to queue ${queueUrl}`
20
- );
21
31
  const buffer = [];
22
32
  const batchSize = 10;
23
33
 
@@ -28,28 +38,23 @@ const QueuerUtil = {
28
38
  });
29
39
  // Sends 10, then purges the buffer
30
40
  if (buffer.length === batchSize) {
31
- console.log('Buffer at 10, sending batch');
32
- await sqs
33
- .sendMessageBatch({
34
- Entries: buffer,
35
- QueueUrl: queueUrl,
36
- })
37
- .promise();
41
+ const command = new SendMessageBatchCommand({
42
+ Entries: buffer,
43
+ QueueUrl: queueUrl,
44
+ });
45
+ await sqs.send(command);
38
46
  // Purge the buffer
39
47
  buffer.splice(0, buffer.length);
40
48
  }
41
49
  }
42
- console.log('Buffer at end, sending final batch');
43
50
 
44
51
  // If any remaining entries under 10 are left in the buffer, send and return
45
52
  if (buffer.length > 0) {
46
- console.log(buffer);
47
- return sqs
48
- .sendMessageBatch({
49
- Entries: buffer,
50
- QueueUrl: queueUrl,
51
- })
52
- .promise();
53
+ const command = new SendMessageBatchCommand({
54
+ Entries: buffer,
55
+ QueueUrl: queueUrl,
56
+ });
57
+ return sqs.send(command);
53
58
  }
54
59
 
55
60
  // If we're exact... just return an empty object for now