@friggframework/core 2.0.0-next.40 → 2.0.0-next.42

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 (196) hide show
  1. package/CLAUDE.md +693 -0
  2. package/README.md +931 -50
  3. package/application/commands/README.md +421 -0
  4. package/application/commands/credential-commands.js +224 -0
  5. package/application/commands/entity-commands.js +315 -0
  6. package/application/commands/integration-commands.js +160 -0
  7. package/application/commands/integration-commands.test.js +123 -0
  8. package/application/commands/user-commands.js +213 -0
  9. package/application/index.js +69 -0
  10. package/core/CLAUDE.md +690 -0
  11. package/core/create-handler.js +0 -6
  12. package/credential/repositories/credential-repository-factory.js +47 -0
  13. package/credential/repositories/credential-repository-interface.js +98 -0
  14. package/credential/repositories/credential-repository-mongo.js +301 -0
  15. package/credential/repositories/credential-repository-postgres.js +307 -0
  16. package/credential/repositories/credential-repository.js +307 -0
  17. package/credential/use-cases/get-credential-for-user.js +21 -0
  18. package/credential/use-cases/update-authentication-status.js +15 -0
  19. package/database/config.js +117 -0
  20. package/database/encryption/README.md +683 -0
  21. package/database/encryption/encryption-integration.test.js +553 -0
  22. package/database/encryption/encryption-schema-registry.js +141 -0
  23. package/database/encryption/encryption-schema-registry.test.js +392 -0
  24. package/database/encryption/field-encryption-service.js +226 -0
  25. package/database/encryption/field-encryption-service.test.js +525 -0
  26. package/database/encryption/logger.js +79 -0
  27. package/database/encryption/mongo-decryption-fix-verification.test.js +348 -0
  28. package/database/encryption/postgres-decryption-fix-verification.test.js +371 -0
  29. package/database/encryption/postgres-relation-decryption.test.js +245 -0
  30. package/database/encryption/prisma-encryption-extension.js +222 -0
  31. package/database/encryption/prisma-encryption-extension.test.js +439 -0
  32. package/database/index.js +25 -12
  33. package/database/models/readme.md +1 -0
  34. package/database/prisma.js +162 -0
  35. package/database/repositories/health-check-repository-factory.js +38 -0
  36. package/database/repositories/health-check-repository-interface.js +86 -0
  37. package/database/repositories/health-check-repository-mongodb.js +72 -0
  38. package/database/repositories/health-check-repository-postgres.js +75 -0
  39. package/database/repositories/health-check-repository.js +108 -0
  40. package/database/use-cases/check-database-health-use-case.js +34 -0
  41. package/database/use-cases/check-encryption-health-use-case.js +82 -0
  42. package/database/use-cases/test-encryption-use-case.js +252 -0
  43. package/encrypt/Cryptor.js +20 -152
  44. package/encrypt/index.js +1 -2
  45. package/encrypt/test-encrypt.js +0 -2
  46. package/handlers/app-definition-loader.js +38 -0
  47. package/handlers/app-handler-helpers.js +0 -3
  48. package/handlers/auth-flow.integration.test.js +147 -0
  49. package/handlers/backend-utils.js +25 -45
  50. package/handlers/integration-event-dispatcher.js +54 -0
  51. package/handlers/integration-event-dispatcher.test.js +141 -0
  52. package/handlers/routers/HEALTHCHECK.md +103 -1
  53. package/handlers/routers/auth.js +3 -14
  54. package/handlers/routers/health.js +63 -424
  55. package/handlers/routers/health.test.js +7 -0
  56. package/handlers/routers/integration-defined-routers.js +8 -5
  57. package/handlers/routers/user.js +25 -5
  58. package/handlers/routers/websocket.js +5 -3
  59. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  60. package/handlers/use-cases/check-integrations-health-use-case.js +32 -0
  61. package/handlers/workers/integration-defined-workers.js +6 -3
  62. package/index.js +45 -22
  63. package/integrations/index.js +12 -10
  64. package/integrations/integration-base.js +224 -53
  65. package/integrations/integration-router.js +386 -178
  66. package/integrations/options.js +1 -1
  67. package/integrations/repositories/integration-mapping-repository-factory.js +50 -0
  68. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  69. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  70. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  71. package/integrations/repositories/integration-mapping-repository.js +156 -0
  72. package/integrations/repositories/integration-repository-factory.js +44 -0
  73. package/integrations/repositories/integration-repository-interface.js +115 -0
  74. package/integrations/repositories/integration-repository-mongo.js +271 -0
  75. package/integrations/repositories/integration-repository-postgres.js +319 -0
  76. package/integrations/tests/doubles/dummy-integration-class.js +90 -0
  77. package/integrations/tests/doubles/test-integration-repository.js +99 -0
  78. package/integrations/tests/use-cases/create-integration.test.js +131 -0
  79. package/integrations/tests/use-cases/delete-integration-for-user.test.js +150 -0
  80. package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +92 -0
  81. package/integrations/tests/use-cases/get-integration-for-user.test.js +150 -0
  82. package/integrations/tests/use-cases/get-integration-instance.test.js +176 -0
  83. package/integrations/tests/use-cases/get-integrations-for-user.test.js +176 -0
  84. package/integrations/tests/use-cases/get-possible-integrations.test.js +188 -0
  85. package/integrations/tests/use-cases/update-integration-messages.test.js +142 -0
  86. package/integrations/tests/use-cases/update-integration-status.test.js +103 -0
  87. package/integrations/tests/use-cases/update-integration.test.js +141 -0
  88. package/integrations/use-cases/create-integration.js +83 -0
  89. package/integrations/use-cases/delete-integration-for-user.js +73 -0
  90. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
  91. package/integrations/use-cases/get-integration-for-user.js +78 -0
  92. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  93. package/integrations/use-cases/get-integration-instance.js +83 -0
  94. package/integrations/use-cases/get-integrations-for-user.js +87 -0
  95. package/integrations/use-cases/get-possible-integrations.js +27 -0
  96. package/integrations/use-cases/index.js +11 -0
  97. package/integrations/use-cases/load-integration-context-full.test.js +329 -0
  98. package/integrations/use-cases/load-integration-context.js +71 -0
  99. package/integrations/use-cases/load-integration-context.test.js +114 -0
  100. package/integrations/use-cases/update-integration-messages.js +44 -0
  101. package/integrations/use-cases/update-integration-status.js +32 -0
  102. package/integrations/use-cases/update-integration.js +93 -0
  103. package/integrations/utils/map-integration-dto.js +36 -0
  104. package/jest-global-setup-noop.js +3 -0
  105. package/jest-global-teardown-noop.js +3 -0
  106. package/{module-plugin → modules}/entity.js +1 -0
  107. package/{module-plugin → modules}/index.js +0 -8
  108. package/modules/module-factory.js +56 -0
  109. package/modules/module-hydration.test.js +205 -0
  110. package/modules/module.js +221 -0
  111. package/modules/repositories/module-repository-factory.js +33 -0
  112. package/modules/repositories/module-repository-interface.js +129 -0
  113. package/modules/repositories/module-repository-mongo.js +386 -0
  114. package/modules/repositories/module-repository-postgres.js +437 -0
  115. package/modules/repositories/module-repository.js +327 -0
  116. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  117. package/{module-plugin → modules}/test/mock-api/definition.js +12 -8
  118. package/modules/tests/doubles/test-module-factory.js +16 -0
  119. package/modules/tests/doubles/test-module-repository.js +39 -0
  120. package/modules/use-cases/get-entities-for-user.js +32 -0
  121. package/modules/use-cases/get-entity-options-by-id.js +59 -0
  122. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  123. package/modules/use-cases/get-module-instance-from-type.js +31 -0
  124. package/modules/use-cases/get-module.js +56 -0
  125. package/modules/use-cases/process-authorization-callback.js +121 -0
  126. package/modules/use-cases/refresh-entity-options.js +59 -0
  127. package/modules/use-cases/test-module-auth.js +55 -0
  128. package/modules/utils/map-module-dto.js +18 -0
  129. package/package.json +14 -6
  130. package/prisma-mongodb/schema.prisma +321 -0
  131. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  132. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  133. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  134. package/prisma-postgresql/schema.prisma +303 -0
  135. package/syncs/manager.js +468 -443
  136. package/syncs/repositories/sync-repository-factory.js +38 -0
  137. package/syncs/repositories/sync-repository-interface.js +109 -0
  138. package/syncs/repositories/sync-repository-mongo.js +239 -0
  139. package/syncs/repositories/sync-repository-postgres.js +319 -0
  140. package/syncs/sync.js +0 -1
  141. package/token/repositories/token-repository-factory.js +33 -0
  142. package/token/repositories/token-repository-interface.js +131 -0
  143. package/token/repositories/token-repository-mongo.js +212 -0
  144. package/token/repositories/token-repository-postgres.js +257 -0
  145. package/token/repositories/token-repository.js +219 -0
  146. package/types/integrations/index.d.ts +2 -6
  147. package/types/module-plugin/index.d.ts +5 -57
  148. package/types/syncs/index.d.ts +0 -2
  149. package/user/repositories/user-repository-factory.js +46 -0
  150. package/user/repositories/user-repository-interface.js +198 -0
  151. package/user/repositories/user-repository-mongo.js +250 -0
  152. package/user/repositories/user-repository-postgres.js +311 -0
  153. package/user/tests/doubles/test-user-repository.js +72 -0
  154. package/user/tests/use-cases/create-individual-user.test.js +24 -0
  155. package/user/tests/use-cases/create-organization-user.test.js +28 -0
  156. package/user/tests/use-cases/create-token-for-user-id.test.js +19 -0
  157. package/user/tests/use-cases/get-user-from-bearer-token.test.js +64 -0
  158. package/user/tests/use-cases/login-user.test.js +140 -0
  159. package/user/use-cases/create-individual-user.js +61 -0
  160. package/user/use-cases/create-organization-user.js +47 -0
  161. package/user/use-cases/create-token-for-user-id.js +30 -0
  162. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  163. package/user/use-cases/login-user.js +122 -0
  164. package/user/user.js +77 -0
  165. package/websocket/repositories/websocket-connection-repository-factory.js +37 -0
  166. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  167. package/websocket/repositories/websocket-connection-repository-mongo.js +155 -0
  168. package/websocket/repositories/websocket-connection-repository-postgres.js +195 -0
  169. package/websocket/repositories/websocket-connection-repository.js +160 -0
  170. package/database/models/State.js +0 -9
  171. package/database/models/Token.js +0 -70
  172. package/database/mongo.js +0 -171
  173. package/encrypt/Cryptor.test.js +0 -32
  174. package/encrypt/encrypt.js +0 -104
  175. package/encrypt/encrypt.test.js +0 -1069
  176. package/handlers/routers/middleware/loadUser.js +0 -15
  177. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  178. package/integrations/create-frigg-backend.js +0 -31
  179. package/integrations/integration-factory.js +0 -251
  180. package/integrations/integration-mapping.js +0 -43
  181. package/integrations/integration-model.js +0 -46
  182. package/integrations/integration-user.js +0 -144
  183. package/integrations/test/integration-base.test.js +0 -144
  184. package/module-plugin/auther.js +0 -393
  185. package/module-plugin/credential.js +0 -22
  186. package/module-plugin/entity-manager.js +0 -70
  187. package/module-plugin/manager.js +0 -169
  188. package/module-plugin/module-factory.js +0 -61
  189. package/module-plugin/test/auther.test.js +0 -97
  190. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  191. /package/{module-plugin → modules}/requester/api-key.js +0 -0
  192. /package/{module-plugin → modules}/requester/basic.js +0 -0
  193. /package/{module-plugin → modules}/requester/oauth-2.js +0 -0
  194. /package/{module-plugin → modules}/requester/requester.js +0 -0
  195. /package/{module-plugin → modules}/requester/requester.test.js +0 -0
  196. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -0,0 +1,315 @@
1
+ -- CreateEnum
2
+ CREATE TYPE "UserType" AS ENUM ('INDIVIDUAL', 'ORGANIZATION');
3
+
4
+ -- CreateEnum
5
+ CREATE TYPE "IntegrationStatus" AS ENUM ('ENABLED', 'NEEDS_CONFIG', 'PROCESSING', 'DISABLED', 'ERROR');
6
+
7
+ -- CreateEnum
8
+ CREATE TYPE "AssociationType" AS ENUM ('ONE_TO_MANY', 'ONE_TO_ONE', 'MANY_TO_ONE');
9
+
10
+ -- CreateTable
11
+ CREATE TABLE "User" (
12
+ "id" SERIAL NOT NULL,
13
+ "type" "UserType" NOT NULL,
14
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
15
+ "updatedAt" TIMESTAMP(3) NOT NULL,
16
+ "email" TEXT,
17
+ "username" TEXT,
18
+ "hashword" TEXT,
19
+ "appUserId" TEXT,
20
+ "organizationId" INTEGER,
21
+ "appOrgId" TEXT,
22
+ "name" TEXT,
23
+
24
+ CONSTRAINT "User_pkey" PRIMARY KEY ("id")
25
+ );
26
+
27
+ -- CreateTable
28
+ CREATE TABLE "Token" (
29
+ "id" SERIAL NOT NULL,
30
+ "token" TEXT NOT NULL,
31
+ "created" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
32
+ "expires" TIMESTAMP(3),
33
+ "userId" INTEGER NOT NULL,
34
+
35
+ CONSTRAINT "Token_pkey" PRIMARY KEY ("id")
36
+ );
37
+
38
+ -- CreateTable
39
+ CREATE TABLE "Credential" (
40
+ "id" SERIAL NOT NULL,
41
+ "userId" INTEGER,
42
+ "subType" TEXT,
43
+ "auth_is_valid" BOOLEAN,
44
+ "externalId" TEXT,
45
+ "data" JSONB NOT NULL DEFAULT '{}',
46
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
47
+ "updatedAt" TIMESTAMP(3) NOT NULL,
48
+
49
+ CONSTRAINT "Credential_pkey" PRIMARY KEY ("id")
50
+ );
51
+
52
+ -- CreateTable
53
+ CREATE TABLE "Entity" (
54
+ "id" SERIAL NOT NULL,
55
+ "credentialId" INTEGER,
56
+ "subType" TEXT,
57
+ "userId" INTEGER,
58
+ "name" TEXT,
59
+ "moduleName" TEXT,
60
+ "externalId" TEXT,
61
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
62
+ "updatedAt" TIMESTAMP(3) NOT NULL,
63
+
64
+ CONSTRAINT "Entity_pkey" PRIMARY KEY ("id")
65
+ );
66
+
67
+ -- CreateTable
68
+ CREATE TABLE "Integration" (
69
+ "id" SERIAL NOT NULL,
70
+ "userId" INTEGER,
71
+ "status" "IntegrationStatus" NOT NULL DEFAULT 'ENABLED',
72
+ "config" JSONB,
73
+ "version" TEXT,
74
+ "entityReferenceMap" JSONB DEFAULT '{}',
75
+ "errors" JSONB NOT NULL DEFAULT '[]',
76
+ "warnings" JSONB NOT NULL DEFAULT '[]',
77
+ "info" JSONB NOT NULL DEFAULT '[]',
78
+ "logs" JSONB NOT NULL DEFAULT '[]',
79
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
80
+ "updatedAt" TIMESTAMP(3) NOT NULL,
81
+
82
+ CONSTRAINT "Integration_pkey" PRIMARY KEY ("id")
83
+ );
84
+
85
+ -- CreateTable
86
+ CREATE TABLE "IntegrationMapping" (
87
+ "id" SERIAL NOT NULL,
88
+ "integrationId" INTEGER NOT NULL,
89
+ "sourceId" TEXT,
90
+ "mapping" JSONB,
91
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
92
+ "updatedAt" TIMESTAMP(3) NOT NULL,
93
+
94
+ CONSTRAINT "IntegrationMapping_pkey" PRIMARY KEY ("id")
95
+ );
96
+
97
+ -- CreateTable
98
+ CREATE TABLE "Sync" (
99
+ "id" SERIAL NOT NULL,
100
+ "integrationId" INTEGER,
101
+ "hash" TEXT NOT NULL,
102
+ "name" TEXT NOT NULL,
103
+
104
+ CONSTRAINT "Sync_pkey" PRIMARY KEY ("id")
105
+ );
106
+
107
+ -- CreateTable
108
+ CREATE TABLE "DataIdentifier" (
109
+ "id" SERIAL NOT NULL,
110
+ "syncId" INTEGER,
111
+ "entityId" INTEGER NOT NULL,
112
+ "idData" JSONB NOT NULL,
113
+ "hash" TEXT NOT NULL,
114
+
115
+ CONSTRAINT "DataIdentifier_pkey" PRIMARY KEY ("id")
116
+ );
117
+
118
+ -- CreateTable
119
+ CREATE TABLE "Association" (
120
+ "id" SERIAL NOT NULL,
121
+ "integrationId" INTEGER NOT NULL,
122
+ "name" TEXT NOT NULL,
123
+ "type" "AssociationType" NOT NULL,
124
+ "primaryObject" TEXT NOT NULL,
125
+
126
+ CONSTRAINT "Association_pkey" PRIMARY KEY ("id")
127
+ );
128
+
129
+ -- CreateTable
130
+ CREATE TABLE "AssociationObject" (
131
+ "id" SERIAL NOT NULL,
132
+ "associationId" INTEGER NOT NULL,
133
+ "entityId" INTEGER NOT NULL,
134
+ "objectType" TEXT NOT NULL,
135
+ "objId" TEXT NOT NULL,
136
+ "metadata" JSONB,
137
+
138
+ CONSTRAINT "AssociationObject_pkey" PRIMARY KEY ("id")
139
+ );
140
+
141
+ -- CreateTable
142
+ CREATE TABLE "State" (
143
+ "id" SERIAL NOT NULL,
144
+ "state" JSONB,
145
+
146
+ CONSTRAINT "State_pkey" PRIMARY KEY ("id")
147
+ );
148
+
149
+ -- CreateTable
150
+ CREATE TABLE "WebsocketConnection" (
151
+ "id" SERIAL NOT NULL,
152
+ "connectionId" TEXT,
153
+
154
+ CONSTRAINT "WebsocketConnection_pkey" PRIMARY KEY ("id")
155
+ );
156
+
157
+ -- CreateTable
158
+ CREATE TABLE "_EntityToIntegration" (
159
+ "A" INTEGER NOT NULL,
160
+ "B" INTEGER NOT NULL,
161
+
162
+ CONSTRAINT "_EntityToIntegration_AB_pkey" PRIMARY KEY ("A","B")
163
+ );
164
+
165
+ -- CreateTable
166
+ CREATE TABLE "_EntityToSync" (
167
+ "A" INTEGER NOT NULL,
168
+ "B" INTEGER NOT NULL,
169
+
170
+ CONSTRAINT "_EntityToSync_AB_pkey" PRIMARY KEY ("A","B")
171
+ );
172
+
173
+ -- CreateIndex
174
+ CREATE INDEX "User_type_idx" ON "User"("type");
175
+
176
+ -- CreateIndex
177
+ CREATE INDEX "User_appUserId_idx" ON "User"("appUserId");
178
+
179
+ -- CreateIndex
180
+ CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
181
+
182
+ -- CreateIndex
183
+ CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
184
+
185
+ -- CreateIndex
186
+ CREATE UNIQUE INDEX "User_appOrgId_key" ON "User"("appOrgId");
187
+
188
+ -- CreateIndex
189
+ CREATE INDEX "Token_userId_idx" ON "Token"("userId");
190
+
191
+ -- CreateIndex
192
+ CREATE INDEX "Token_expires_idx" ON "Token"("expires");
193
+
194
+ -- CreateIndex
195
+ CREATE INDEX "Credential_userId_idx" ON "Credential"("userId");
196
+
197
+ -- CreateIndex
198
+ CREATE INDEX "Credential_externalId_idx" ON "Credential"("externalId");
199
+
200
+ -- CreateIndex
201
+ CREATE INDEX "Entity_userId_idx" ON "Entity"("userId");
202
+
203
+ -- CreateIndex
204
+ CREATE INDEX "Entity_externalId_idx" ON "Entity"("externalId");
205
+
206
+ -- CreateIndex
207
+ CREATE INDEX "Entity_moduleName_idx" ON "Entity"("moduleName");
208
+
209
+ -- CreateIndex
210
+ CREATE INDEX "Entity_credentialId_idx" ON "Entity"("credentialId");
211
+
212
+ -- CreateIndex
213
+ CREATE INDEX "Integration_userId_idx" ON "Integration"("userId");
214
+
215
+ -- CreateIndex
216
+ CREATE INDEX "Integration_status_idx" ON "Integration"("status");
217
+
218
+ -- CreateIndex
219
+ CREATE INDEX "IntegrationMapping_integrationId_idx" ON "IntegrationMapping"("integrationId");
220
+
221
+ -- CreateIndex
222
+ CREATE INDEX "IntegrationMapping_sourceId_idx" ON "IntegrationMapping"("sourceId");
223
+
224
+ -- CreateIndex
225
+ CREATE UNIQUE INDEX "IntegrationMapping_integrationId_sourceId_key" ON "IntegrationMapping"("integrationId", "sourceId");
226
+
227
+ -- CreateIndex
228
+ CREATE INDEX "Sync_integrationId_idx" ON "Sync"("integrationId");
229
+
230
+ -- CreateIndex
231
+ CREATE INDEX "Sync_hash_idx" ON "Sync"("hash");
232
+
233
+ -- CreateIndex
234
+ CREATE INDEX "Sync_name_idx" ON "Sync"("name");
235
+
236
+ -- CreateIndex
237
+ CREATE INDEX "DataIdentifier_syncId_idx" ON "DataIdentifier"("syncId");
238
+
239
+ -- CreateIndex
240
+ CREATE INDEX "DataIdentifier_entityId_idx" ON "DataIdentifier"("entityId");
241
+
242
+ -- CreateIndex
243
+ CREATE INDEX "DataIdentifier_hash_idx" ON "DataIdentifier"("hash");
244
+
245
+ -- CreateIndex
246
+ CREATE INDEX "Association_integrationId_idx" ON "Association"("integrationId");
247
+
248
+ -- CreateIndex
249
+ CREATE INDEX "Association_name_idx" ON "Association"("name");
250
+
251
+ -- CreateIndex
252
+ CREATE INDEX "AssociationObject_associationId_idx" ON "AssociationObject"("associationId");
253
+
254
+ -- CreateIndex
255
+ CREATE INDEX "AssociationObject_entityId_idx" ON "AssociationObject"("entityId");
256
+
257
+ -- CreateIndex
258
+ CREATE INDEX "WebsocketConnection_connectionId_idx" ON "WebsocketConnection"("connectionId");
259
+
260
+ -- CreateIndex
261
+ CREATE INDEX "_EntityToIntegration_B_index" ON "_EntityToIntegration"("B");
262
+
263
+ -- CreateIndex
264
+ CREATE INDEX "_EntityToSync_B_index" ON "_EntityToSync"("B");
265
+
266
+ -- AddForeignKey
267
+ ALTER TABLE "User" ADD CONSTRAINT "User_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
268
+
269
+ -- AddForeignKey
270
+ ALTER TABLE "Token" ADD CONSTRAINT "Token_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
271
+
272
+ -- AddForeignKey
273
+ ALTER TABLE "Credential" ADD CONSTRAINT "Credential_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
274
+
275
+ -- AddForeignKey
276
+ ALTER TABLE "Entity" ADD CONSTRAINT "Entity_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "Credential"("id") ON DELETE SET NULL ON UPDATE CASCADE;
277
+
278
+ -- AddForeignKey
279
+ ALTER TABLE "Entity" ADD CONSTRAINT "Entity_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
280
+
281
+ -- AddForeignKey
282
+ ALTER TABLE "Integration" ADD CONSTRAINT "Integration_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
283
+
284
+ -- AddForeignKey
285
+ ALTER TABLE "IntegrationMapping" ADD CONSTRAINT "IntegrationMapping_integrationId_fkey" FOREIGN KEY ("integrationId") REFERENCES "Integration"("id") ON DELETE CASCADE ON UPDATE CASCADE;
286
+
287
+ -- AddForeignKey
288
+ ALTER TABLE "Sync" ADD CONSTRAINT "Sync_integrationId_fkey" FOREIGN KEY ("integrationId") REFERENCES "Integration"("id") ON DELETE CASCADE ON UPDATE CASCADE;
289
+
290
+ -- AddForeignKey
291
+ ALTER TABLE "DataIdentifier" ADD CONSTRAINT "DataIdentifier_syncId_fkey" FOREIGN KEY ("syncId") REFERENCES "Sync"("id") ON DELETE CASCADE ON UPDATE CASCADE;
292
+
293
+ -- AddForeignKey
294
+ ALTER TABLE "DataIdentifier" ADD CONSTRAINT "DataIdentifier_entityId_fkey" FOREIGN KEY ("entityId") REFERENCES "Entity"("id") ON DELETE CASCADE ON UPDATE CASCADE;
295
+
296
+ -- AddForeignKey
297
+ ALTER TABLE "Association" ADD CONSTRAINT "Association_integrationId_fkey" FOREIGN KEY ("integrationId") REFERENCES "Integration"("id") ON DELETE CASCADE ON UPDATE CASCADE;
298
+
299
+ -- AddForeignKey
300
+ ALTER TABLE "AssociationObject" ADD CONSTRAINT "AssociationObject_associationId_fkey" FOREIGN KEY ("associationId") REFERENCES "Association"("id") ON DELETE CASCADE ON UPDATE CASCADE;
301
+
302
+ -- AddForeignKey
303
+ ALTER TABLE "AssociationObject" ADD CONSTRAINT "AssociationObject_entityId_fkey" FOREIGN KEY ("entityId") REFERENCES "Entity"("id") ON DELETE CASCADE ON UPDATE CASCADE;
304
+
305
+ -- AddForeignKey
306
+ ALTER TABLE "_EntityToIntegration" ADD CONSTRAINT "_EntityToIntegration_A_fkey" FOREIGN KEY ("A") REFERENCES "Entity"("id") ON DELETE CASCADE ON UPDATE CASCADE;
307
+
308
+ -- AddForeignKey
309
+ ALTER TABLE "_EntityToIntegration" ADD CONSTRAINT "_EntityToIntegration_B_fkey" FOREIGN KEY ("B") REFERENCES "Integration"("id") ON DELETE CASCADE ON UPDATE CASCADE;
310
+
311
+ -- AddForeignKey
312
+ ALTER TABLE "_EntityToSync" ADD CONSTRAINT "_EntityToSync_A_fkey" FOREIGN KEY ("A") REFERENCES "Entity"("id") ON DELETE CASCADE ON UPDATE CASCADE;
313
+
314
+ -- AddForeignKey
315
+ ALTER TABLE "_EntityToSync" ADD CONSTRAINT "_EntityToSync_B_fkey" FOREIGN KEY ("B") REFERENCES "Sync"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,9 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - You are about to drop the column `auth_is_valid` on the `Credential` table. All the data in the column will be lost.
5
+
6
+ */
7
+ -- AlterTable
8
+ ALTER TABLE "Credential" DROP COLUMN "auth_is_valid",
9
+ ADD COLUMN "authIsValid" BOOLEAN;
@@ -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,303 @@
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 = "../node_modules/@prisma-postgresql/client"
8
+ }
9
+
10
+ datasource db {
11
+ provider = "postgresql"
12
+ url = env("DATABASE_URL")
13
+ }
14
+
15
+ // ============================================================================
16
+ // USER MODELS
17
+ // ============================================================================
18
+
19
+ /// User model with discriminator pattern support
20
+ /// Replaces Mongoose discriminators (IndividualUser, OrganizationUser)
21
+ model User {
22
+ id Int @id @default(autoincrement())
23
+ type UserType
24
+
25
+ // Timestamps
26
+ createdAt DateTime @default(now())
27
+ updatedAt DateTime @updatedAt
28
+
29
+ // IndividualUser fields (nullable for organizations)
30
+ email String?
31
+ username String?
32
+ hashword String? // Bcrypt hashed password (handled in application layer)
33
+ appUserId String?
34
+ organizationId Int?
35
+
36
+ // Self-referential relation for organization membership
37
+ organization User? @relation("OrgMembers", fields: [organizationId], references: [id], onDelete: NoAction, onUpdate: NoAction)
38
+ members User[] @relation("OrgMembers")
39
+
40
+ // OrganizationUser fields (nullable for individuals)
41
+ appOrgId String?
42
+ name String?
43
+
44
+ // Relations
45
+ tokens Token[]
46
+ credentials Credential[]
47
+ entities Entity[]
48
+ integrations Integration[]
49
+
50
+ @@unique([email])
51
+ @@unique([username])
52
+ @@unique([appOrgId])
53
+ @@index([type])
54
+ @@index([appUserId])
55
+ }
56
+
57
+ enum UserType {
58
+ INDIVIDUAL
59
+ ORGANIZATION
60
+ }
61
+
62
+ // ============================================================================
63
+ // AUTHENTICATION MODELS
64
+ // ============================================================================
65
+
66
+ /// Authentication tokens with expiration
67
+ /// Bcrypt hashed tokens stored (handled in application layer)
68
+ model Token {
69
+ id Int @id @default(autoincrement())
70
+ token String // Bcrypt hashed
71
+ created DateTime @default(now())
72
+ expires DateTime?
73
+ userId Int
74
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
75
+
76
+ @@index([userId])
77
+ @@index([expires])
78
+ }
79
+
80
+ // ============================================================================
81
+ // CREDENTIAL & ENTITY MODELS
82
+ // ============================================================================
83
+
84
+ /// OAuth credentials and API tokens
85
+ /// All sensitive data encrypted with KMS at rest
86
+ model Credential {
87
+ id Int @id @default(autoincrement())
88
+ userId Int?
89
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
90
+ subType String?
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
+ subType String?
114
+ userId Int?
115
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
116
+ name String?
117
+ moduleName String?
118
+ externalId String?
119
+
120
+ createdAt DateTime @default(now())
121
+ updatedAt DateTime @updatedAt
122
+
123
+ // Relations - many-to-many with implicit join tables
124
+ integrations Integration[]
125
+ syncs Sync[]
126
+
127
+ dataIdentifiers DataIdentifier[]
128
+ associationObjects AssociationObject[]
129
+
130
+ @@index([userId])
131
+ @@index([externalId])
132
+ @@index([moduleName])
133
+ @@index([credentialId])
134
+ }
135
+
136
+ // ============================================================================
137
+ // INTEGRATION MODELS
138
+ // ============================================================================
139
+
140
+ /// Main integration configuration and state
141
+ model Integration {
142
+ id Int @id @default(autoincrement())
143
+ userId Int?
144
+ user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
145
+ status IntegrationStatus @default(ENABLED)
146
+
147
+ // Configuration and version
148
+ config Json? // Integration configuration object
149
+ version String?
150
+
151
+ // Entity references (many-to-many via implicit join table)
152
+ entities Entity[]
153
+
154
+ // Entity reference map (Map<String, String> stored as JSON)
155
+ entityReferenceMap Json? @default("{}")
156
+
157
+ // Message arrays (stored as JSON)
158
+ errors Json @default("[]")
159
+ warnings Json @default("[]")
160
+ info Json @default("[]")
161
+ logs Json @default("[]")
162
+
163
+ createdAt DateTime @default(now())
164
+ updatedAt DateTime @updatedAt
165
+
166
+ // Relations
167
+ associations Association[]
168
+ syncs Sync[]
169
+ mappings IntegrationMapping[]
170
+
171
+ @@index([userId])
172
+ @@index([status])
173
+ }
174
+
175
+ enum IntegrationStatus {
176
+ ENABLED
177
+ NEEDS_CONFIG
178
+ PROCESSING
179
+ DISABLED
180
+ ERROR
181
+ }
182
+
183
+ /// Integration-specific data mappings
184
+ /// All mapping data encrypted with KMS
185
+ model IntegrationMapping {
186
+ id Int @id @default(autoincrement())
187
+ integrationId Int
188
+ integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
189
+ sourceId String?
190
+
191
+ // Encrypted mapping data (handled via Prisma middleware)
192
+ mapping Json?
193
+
194
+ createdAt DateTime @default(now())
195
+ updatedAt DateTime @updatedAt
196
+
197
+ @@unique([integrationId, sourceId])
198
+ @@index([integrationId])
199
+ @@index([sourceId])
200
+ }
201
+
202
+ // ============================================================================
203
+ // SYNC MODELS
204
+ // ============================================================================
205
+
206
+ /// Bidirectional data synchronization tracking
207
+ model Sync {
208
+ id Int @id @default(autoincrement())
209
+ integrationId Int?
210
+ integration Integration? @relation(fields: [integrationId], references: [id], onDelete: Cascade)
211
+
212
+ // Entity references (many-to-many via implicit join table)
213
+ entities Entity[]
214
+
215
+ hash String
216
+ name String
217
+
218
+ // Data identifiers (extracted to separate model)
219
+ dataIdentifiers DataIdentifier[]
220
+
221
+ @@index([integrationId])
222
+ @@index([hash])
223
+ @@index([name])
224
+ }
225
+
226
+ /// Data identifier for sync operations
227
+ /// Replaces nested array structure in Mongoose
228
+ model DataIdentifier {
229
+ id Int @id @default(autoincrement())
230
+ syncId Int?
231
+ sync Sync? @relation(fields: [syncId], references: [id], onDelete: Cascade)
232
+ entityId Int
233
+ entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)
234
+
235
+ // Identifier data (can be any structure)
236
+ idData Json
237
+
238
+ hash String
239
+
240
+ @@index([syncId])
241
+ @@index([entityId])
242
+ @@index([hash])
243
+ }
244
+
245
+ // ============================================================================
246
+ // ASSOCIATION MODELS
247
+ // ============================================================================
248
+
249
+ /// Entity associations with cardinality tracking
250
+ model Association {
251
+ id Int @id @default(autoincrement())
252
+ integrationId Int
253
+ integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
254
+ name String
255
+ type AssociationType
256
+ primaryObject String
257
+
258
+ // Associated objects (extracted to separate model)
259
+ objects AssociationObject[]
260
+
261
+ @@index([integrationId])
262
+ @@index([name])
263
+ }
264
+
265
+ /// Association object entry
266
+ /// Replaces nested array structure in Mongoose
267
+ model AssociationObject {
268
+ id Int @id @default(autoincrement())
269
+ associationId Int
270
+ association Association @relation(fields: [associationId], references: [id], onDelete: Cascade)
271
+ entityId Int
272
+ entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)
273
+ objectType String
274
+ objId String
275
+ metadata Json? // Optional metadata
276
+
277
+ @@index([associationId])
278
+ @@index([entityId])
279
+ }
280
+
281
+ enum AssociationType {
282
+ ONE_TO_MANY
283
+ ONE_TO_ONE
284
+ MANY_TO_ONE
285
+ }
286
+
287
+ // ============================================================================
288
+ // UTILITY MODELS
289
+ // ============================================================================
290
+
291
+ /// Generic state storage
292
+ model State {
293
+ id Int @id @default(autoincrement())
294
+ state Json?
295
+ }
296
+
297
+ /// AWS API Gateway WebSocket connection tracking
298
+ model WebsocketConnection {
299
+ id Int @id @default(autoincrement())
300
+ connectionId String?
301
+
302
+ @@index([connectionId])
303
+ }