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