@friggframework/core 2.0.0-next.11 → 2.0.0-next.110
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 +702 -0
- package/README.md +999 -50
- package/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-script-execution-repository-interface.js +171 -0
- package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +238 -0
- package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +278 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/README.md +451 -0
- package/application/commands/admin-script-commands.js +359 -0
- package/application/commands/credential-commands.js +262 -0
- package/application/commands/entity-commands.js +336 -0
- package/application/commands/integration-commands.js +356 -0
- package/application/commands/integration-mapping-commands.js +25 -0
- package/application/commands/process-commands.js +135 -0
- package/application/commands/report-commands.js +188 -0
- package/application/commands/scheduler-commands.js +263 -0
- package/application/commands/usage-commands.js +56 -0
- package/application/commands/user-commands.js +312 -0
- package/application/index.js +83 -0
- package/artifacts/repositories/artifact-repository-factory.js +19 -0
- package/artifacts/repositories/artifact-repository-interface.js +27 -0
- package/artifacts/repositories/artifact-repository-local.js +42 -0
- package/artifacts/repositories/artifact-repository-s3.js +61 -0
- package/assertions/index.js +0 -3
- package/core/CLAUDE.md +700 -0
- package/core/Worker.js +60 -24
- package/core/create-handler.js +189 -5
- package/core/parameters-to-env.js +257 -0
- package/core/ssm-preload.mjs +34 -0
- package/credential/repositories/credential-active-type.js +32 -0
- package/credential/repositories/credential-repository-documentdb.js +355 -0
- package/credential/repositories/credential-repository-factory.js +54 -0
- package/credential/repositories/credential-repository-interface.js +113 -0
- package/credential/repositories/credential-repository-mongo.js +294 -0
- package/credential/repositories/credential-repository-postgres.js +312 -0
- package/credential/repositories/credential-repository.js +300 -0
- package/credential/use-cases/get-credential-for-user.js +25 -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/documentdb-encryption-service.js +330 -0
- package/database/documentdb-utils.js +192 -0
- package/database/encryption/README.md +839 -0
- package/database/encryption/documentdb-encryption-service.md +3575 -0
- package/database/encryption/encryption-schema-registry.js +401 -0
- package/database/encryption/field-encryption-service.js +254 -0
- package/database/encryption/logger.js +79 -0
- package/database/encryption/prisma-encryption-extension.js +230 -0
- package/database/index.js +21 -21
- package/database/prisma.js +182 -0
- package/database/repositories/health-check-repository-documentdb.js +138 -0
- package/database/repositories/health-check-repository-factory.js +48 -0
- package/database/repositories/health-check-repository-interface.js +82 -0
- package/database/repositories/health-check-repository-mongodb.js +89 -0
- package/database/repositories/health-check-repository-postgres.js +82 -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/resolve-migration-via-worker-use-case.js +49 -0
- package/database/use-cases/run-database-migration-use-case.js +139 -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 +94 -0
- package/database/utils/mongodb-schema-init.js +108 -0
- package/database/utils/prisma-runner.js +491 -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/errors/client-safe-error.js +26 -0
- package/errors/fetch-error.js +15 -7
- package/errors/index.js +2 -0
- package/generated/prisma-mongodb/client.d.ts +1 -0
- package/generated/prisma-mongodb/client.js +5 -0
- package/generated/prisma-mongodb/default.d.ts +1 -0
- package/generated/prisma-mongodb/default.js +5 -0
- package/generated/prisma-mongodb/edge.d.ts +1 -0
- package/generated/prisma-mongodb/edge.js +386 -0
- package/generated/prisma-mongodb/index-browser.js +368 -0
- package/generated/prisma-mongodb/index.d.ts +27065 -0
- package/generated/prisma-mongodb/index.js +411 -0
- package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-mongodb/package.json +183 -0
- package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
- package/generated/prisma-mongodb/runtime/edge.js +35 -0
- package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
- package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
- package/generated/prisma-mongodb/runtime/library.js +147 -0
- package/generated/prisma-mongodb/runtime/react-native.js +84 -0
- package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-mongodb/schema.prisma +455 -0
- package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-mongodb/wasm.d.ts +1 -0
- package/generated/prisma-mongodb/wasm.js +393 -0
- package/generated/prisma-postgresql/client.d.ts +1 -0
- package/generated/prisma-postgresql/client.js +5 -0
- package/generated/prisma-postgresql/default.d.ts +1 -0
- package/generated/prisma-postgresql/default.js +5 -0
- package/generated/prisma-postgresql/edge.d.ts +1 -0
- package/generated/prisma-postgresql/edge.js +407 -0
- package/generated/prisma-postgresql/index-browser.js +389 -0
- package/generated/prisma-postgresql/index.d.ts +29904 -0
- package/generated/prisma-postgresql/index.js +432 -0
- package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
- package/generated/prisma-postgresql/package.json +183 -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/edge-esm.js +35 -0
- package/generated/prisma-postgresql/runtime/edge.js +35 -0
- package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
- package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
- package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
- package/generated/prisma-postgresql/runtime/library.js +147 -0
- package/generated/prisma-postgresql/runtime/react-native.js +84 -0
- package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
- package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
- package/generated/prisma-postgresql/schema.prisma +436 -0
- package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
- package/generated/prisma-postgresql/wasm.d.ts +1 -0
- package/generated/prisma-postgresql/wasm.js +414 -0
- package/handlers/WEBHOOKS.md +653 -0
- package/handlers/app-definition-loader.js +67 -0
- package/handlers/app-handler-helpers.js +3 -3
- package/handlers/backend-utils.js +271 -42
- package/handlers/database-migration-handler.js +227 -0
- package/handlers/integration-event-dispatcher.js +68 -0
- package/handlers/middleware/admin-auth.js +73 -0
- package/handlers/routers/HEALTHCHECK.md +342 -0
- package/handlers/routers/auth.js +4 -15
- package/handlers/routers/db-migration.handler.js +29 -0
- package/handlers/routers/db-migration.js +329 -0
- package/handlers/routers/health.js +518 -0
- package/handlers/routers/integration-defined-routers.js +85 -10
- package/handlers/routers/integration-webhook-routers.js +80 -0
- package/handlers/routers/user.js +27 -5
- package/handlers/routers/websocket.js +5 -3
- 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 +427 -0
- package/handlers/workers/dlq-processor.js +63 -0
- package/handlers/workers/integration-defined-workers.js +13 -7
- package/index.js +102 -46
- package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
- package/infrastructure/scheduler/index.js +33 -0
- package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
- package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
- package/integrations/EXTENSIONS.md +240 -0
- package/integrations/WEBHOOK-QUICKSTART.md +151 -0
- package/integrations/extension.js +254 -0
- package/integrations/index.js +20 -10
- package/integrations/integration-base.js +730 -74
- package/integrations/integration-router.js +398 -180
- package/integrations/options.js +1 -1
- package/integrations/repositories/config-patch-shared.js +43 -0
- package/integrations/repositories/integration-mapping-repository-documentdb.js +303 -0
- package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +120 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +183 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +255 -0
- package/integrations/repositories/integration-mapping-repository.js +156 -0
- package/integrations/repositories/integration-repository-documentdb.js +322 -0
- package/integrations/repositories/integration-repository-factory.js +51 -0
- package/integrations/repositories/integration-repository-interface.js +189 -0
- package/integrations/repositories/integration-repository-mongo.js +450 -0
- package/integrations/repositories/integration-repository-postgres.js +492 -0
- package/integrations/repositories/process-repository-documentdb.js +311 -0
- package/integrations/repositories/process-repository-factory.js +53 -0
- package/integrations/repositories/process-repository-interface.js +136 -0
- package/integrations/repositories/process-repository-mongo.js +262 -0
- package/integrations/repositories/process-repository-postgres.js +380 -0
- package/integrations/repositories/process-update-ops-shared.js +112 -0
- package/integrations/repositories/report-id.js +13 -0
- package/integrations/tests/doubles/config-capturing-integration.js +81 -0
- package/integrations/tests/doubles/dummy-integration-class.js +113 -0
- package/integrations/tests/doubles/test-integration-repository.js +146 -0
- package/integrations/use-cases/create-integration.js +215 -0
- package/integrations/use-cases/create-process.js +130 -0
- package/integrations/use-cases/delete-integration-for-user.js +119 -0
- package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
- package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -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 +88 -0
- package/integrations/use-cases/get-possible-integrations.js +27 -0
- package/integrations/use-cases/get-process.js +89 -0
- package/integrations/use-cases/index.js +19 -0
- package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
- package/integrations/use-cases/load-integration-context.js +71 -0
- package/integrations/use-cases/patch-integration-config.js +39 -0
- package/integrations/use-cases/process-errors.js +28 -0
- package/integrations/use-cases/update-integration-config.js +32 -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 +92 -0
- package/integrations/use-cases/update-process-metrics.js +222 -0
- package/integrations/use-cases/update-process-state.js +163 -0
- package/integrations/utils/map-integration-dto.js +37 -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}/index.js +0 -10
- package/modules/module-factory.js +56 -0
- package/modules/module.js +307 -0
- package/modules/repositories/module-repository-documentdb.js +350 -0
- package/modules/repositories/module-repository-factory.js +40 -0
- package/modules/repositories/module-repository-interface.js +145 -0
- package/modules/repositories/module-repository-mongo.js +436 -0
- package/modules/repositories/module-repository-postgres.js +481 -0
- package/modules/repositories/module-repository.js +369 -0
- package/modules/requester/api-key.js +52 -0
- package/modules/requester/oauth-2.js +555 -0
- package/modules/requester/requester.js +542 -0
- package/{module-plugin → modules}/test/mock-api/api.js +8 -3
- package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
- 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 +71 -0
- package/modules/use-cases/get-entity-options-by-type.js +34 -0
- package/modules/use-cases/get-module-instance-from-type.js +34 -0
- package/modules/use-cases/get-module.js +74 -0
- package/modules/use-cases/process-authorization-callback.js +243 -0
- package/modules/use-cases/refresh-entity-options.js +72 -0
- package/modules/use-cases/test-module-auth.js +72 -0
- package/modules/utils/map-module-dto.js +18 -0
- package/package.json +92 -50
- package/prisma-mongodb/schema.prisma +455 -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/20251112195422_update_user_unique_constraints/migration.sql +25 -0
- package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
- package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
- package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
- package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
- package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
- package/prisma-postgresql/migrations/20260705000000_create_usage_counter/migration.sql +26 -0
- package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
- package/prisma-postgresql/migrations/migration_lock.toml +3 -0
- package/prisma-postgresql/schema.prisma +436 -0
- package/queues/queuer-util.js +103 -21
- package/reporting/README.md +154 -0
- package/reporting/builtin-reports.js +6 -0
- package/reporting/index.js +13 -0
- package/reporting/report-base.js +49 -0
- package/reporting/reports/integrations-report.js +221 -0
- package/syncs/manager.js +468 -443
- package/syncs/repositories/sync-repository-documentdb.js +240 -0
- package/syncs/repositories/sync-repository-factory.js +43 -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/telemetry/README.md +331 -0
- package/telemetry/bind-telemetry-context.js +73 -0
- package/telemetry/canonical-counters.js +52 -0
- package/telemetry/exporters.js +85 -0
- package/telemetry/index.js +26 -0
- package/telemetry/instrument-handler.js +87 -0
- package/telemetry/no-op-telemetry.js +67 -0
- package/telemetry/north-star.js +103 -0
- package/telemetry/otel-telemetry.js +213 -0
- package/telemetry/plugin-subscribers.js +77 -0
- package/telemetry/telemetry-config.js +120 -0
- package/telemetry/telemetry-context.js +40 -0
- package/telemetry/telemetry-event-bus.js +58 -0
- package/telemetry/telemetry-runtime.js +147 -0
- package/telemetry/telemetry-service.js +51 -0
- package/telemetry/usage-rollup-subscriber.js +116 -0
- package/token/repositories/token-repository-documentdb.js +137 -0
- package/token/repositories/token-repository-factory.js +40 -0
- package/token/repositories/token-repository-interface.js +131 -0
- package/token/repositories/token-repository-mongo.js +219 -0
- package/token/repositories/token-repository-postgres.js +264 -0
- package/token/repositories/token-repository.js +219 -0
- package/types/associations/index.d.ts +0 -17
- package/types/core/index.d.ts +12 -4
- package/types/database/index.d.ts +10 -2
- package/types/encrypt/index.d.ts +5 -3
- package/types/integrations/index.d.ts +3 -8
- package/types/module-plugin/index.d.ts +20 -69
- package/types/syncs/index.d.ts +0 -17
- package/usage/README.md +54 -0
- package/usage/index.js +17 -0
- package/usage/repositories/usage-repository-documentdb.js +194 -0
- package/usage/repositories/usage-repository-factory.js +25 -0
- package/usage/repositories/usage-repository-interface.js +37 -0
- package/usage/repositories/usage-repository-prisma.js +146 -0
- package/usage/tracked-metrics.js +38 -0
- package/usage/usage-windows.js +24 -0
- package/user/repositories/user-repository-documentdb.js +458 -0
- package/user/repositories/user-repository-factory.js +52 -0
- package/user/repositories/user-repository-interface.js +214 -0
- package/user/repositories/user-repository-mongo.js +323 -0
- package/user/repositories/user-repository-postgres.js +377 -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 +132 -0
- package/user/use-cases/login-user.js +122 -0
- package/user/user.js +125 -0
- package/utils/backend-path.js +38 -0
- package/utils/index.js +6 -0
- package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
- package/websocket/repositories/websocket-connection-repository-factory.js +44 -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/assertions/is-equal.js +0 -17
- package/associations/model.js +0 -54
- package/database/models/IndividualUser.js +0 -76
- package/database/models/OrganizationUser.js +0 -29
- package/database/models/State.js +0 -9
- package/database/models/Token.js +0 -70
- package/database/models/UserModel.js +0 -7
- package/database/models/WebsocketConnection.js +0 -49
- package/database/mongo.js +0 -45
- package/database/mongoose.js +0 -5
- package/encrypt/Cryptor.test.js +0 -32
- package/encrypt/encrypt.js +0 -132
- package/encrypt/encrypt.test.js +0 -1069
- package/encrypt/test-encrypt.js +0 -107
- 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/handlers/routers/middleware/loadUser.js +0 -15
- package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
- 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/entity.js +0 -46
- package/module-plugin/manager.js +0 -169
- package/module-plugin/module-factory.js +0 -61
- package/module-plugin/requester/api-key.js +0 -36
- package/module-plugin/requester/oauth-2.js +0 -219
- package/module-plugin/requester/requester.js +0 -165
- package/module-plugin/requester/requester.test.js +0 -28
- package/module-plugin/test/auther.test.js +0 -97
- package/syncs/model.js +0 -62
- /package/{module-plugin → modules}/ModuleConstants.js +0 -0
- /package/{module-plugin → modules}/requester/basic.js +0 -0
- /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
toObjectId,
|
|
4
|
+
toObjectIdArray,
|
|
5
|
+
fromObjectId,
|
|
6
|
+
findMany,
|
|
7
|
+
findManyDrained,
|
|
8
|
+
findOne,
|
|
9
|
+
insertOne,
|
|
10
|
+
updateOne,
|
|
11
|
+
deleteOne,
|
|
12
|
+
} = require('../../database/documentdb-utils');
|
|
13
|
+
const {
|
|
14
|
+
IntegrationRepositoryInterface,
|
|
15
|
+
} = require('./integration-repository-interface');
|
|
16
|
+
const { validateConfigPatch } = require('./config-patch-shared');
|
|
17
|
+
|
|
18
|
+
class IntegrationRepositoryDocumentDB extends IntegrationRepositoryInterface {
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.prisma = prisma;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async findIntegrationsByUserId(userId) {
|
|
25
|
+
const objectId = toObjectId(userId);
|
|
26
|
+
const filter = objectId ? { userId: objectId } : {};
|
|
27
|
+
const records = await findMany(this.prisma, 'Integration', filter);
|
|
28
|
+
return records.map((doc) => this._mapIntegration(doc));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async findIntegrations({ type, status } = {}) {
|
|
32
|
+
const filter = {};
|
|
33
|
+
if (type) {
|
|
34
|
+
filter['config.type'] = type;
|
|
35
|
+
}
|
|
36
|
+
if (status) {
|
|
37
|
+
filter.status = status;
|
|
38
|
+
}
|
|
39
|
+
const records = await findMany(this.prisma, 'Integration', filter);
|
|
40
|
+
return records.map((doc) => this._mapIntegration(doc));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async findIntegrationsByEntityId(entityId) {
|
|
44
|
+
const objectId = toObjectId(entityId);
|
|
45
|
+
if (!objectId) return [];
|
|
46
|
+
const records = await findMany(this.prisma, 'Integration', {
|
|
47
|
+
entityIds: objectId,
|
|
48
|
+
});
|
|
49
|
+
return records.map((doc) => this._mapIntegration(doc));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async deleteIntegrationById(integrationId) {
|
|
53
|
+
const objectId = toObjectId(integrationId);
|
|
54
|
+
if (!objectId) return { acknowledged: true, deletedCount: 0 };
|
|
55
|
+
const result = await deleteOne(this.prisma, 'Integration', { _id: objectId });
|
|
56
|
+
const deleted = result?.n ?? 0;
|
|
57
|
+
return { acknowledged: true, deletedCount: deleted };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async findIntegrationByName(name) {
|
|
61
|
+
const doc = await findOne(this.prisma, 'Integration', { 'config.type': name });
|
|
62
|
+
if (!doc) {
|
|
63
|
+
throw new Error(`Integration with name ${name} not found`);
|
|
64
|
+
}
|
|
65
|
+
return this._mapIntegration(doc);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async findIntegrationById(id) {
|
|
69
|
+
const objectId = toObjectId(id);
|
|
70
|
+
if (!objectId) {
|
|
71
|
+
throw new Error(`Integration with id ${id} not found`);
|
|
72
|
+
}
|
|
73
|
+
const doc = await findOne(this.prisma, 'Integration', { _id: objectId });
|
|
74
|
+
if (!doc) {
|
|
75
|
+
throw new Error(`Integration with id ${id} not found`);
|
|
76
|
+
}
|
|
77
|
+
return this._mapIntegration(doc);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async updateIntegrationStatus(integrationId, status) {
|
|
81
|
+
const objectId = toObjectId(integrationId);
|
|
82
|
+
if (!objectId) return false;
|
|
83
|
+
await updateOne(
|
|
84
|
+
this.prisma,
|
|
85
|
+
'Integration',
|
|
86
|
+
{ _id: objectId },
|
|
87
|
+
{
|
|
88
|
+
$set: { status, updatedAt: new Date() },
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async updateIntegrationMessages(
|
|
95
|
+
integrationId,
|
|
96
|
+
messageType,
|
|
97
|
+
messageTitle,
|
|
98
|
+
messageBody,
|
|
99
|
+
messageTimestamp
|
|
100
|
+
) {
|
|
101
|
+
const objectId = toObjectId(integrationId);
|
|
102
|
+
if (!objectId) {
|
|
103
|
+
throw new Error(`Integration ${integrationId} not found`);
|
|
104
|
+
}
|
|
105
|
+
const existing = await findOne(this.prisma, 'Integration', { _id: objectId });
|
|
106
|
+
if (!existing) {
|
|
107
|
+
throw new Error(`Integration ${integrationId} not found`);
|
|
108
|
+
}
|
|
109
|
+
const messages = this._extractMessages(existing);
|
|
110
|
+
const list = Array.isArray(messages[messageType]) ? [...messages[messageType]] : [];
|
|
111
|
+
list.push({
|
|
112
|
+
title: messageTitle ?? null,
|
|
113
|
+
message: messageBody,
|
|
114
|
+
timestamp: messageTimestamp,
|
|
115
|
+
});
|
|
116
|
+
const updatedMessages = { ...messages, [messageType]: list };
|
|
117
|
+
await updateOne(
|
|
118
|
+
this.prisma,
|
|
119
|
+
'Integration',
|
|
120
|
+
{ _id: objectId },
|
|
121
|
+
{
|
|
122
|
+
$set: {
|
|
123
|
+
messages: updatedMessages,
|
|
124
|
+
errors: updatedMessages.errors ?? [],
|
|
125
|
+
warnings: updatedMessages.warnings ?? [],
|
|
126
|
+
info: updatedMessages.info ?? [],
|
|
127
|
+
logs: updatedMessages.logs ?? [],
|
|
128
|
+
updatedAt: new Date(),
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async createIntegration(entities, userId, config) {
|
|
136
|
+
const now = new Date();
|
|
137
|
+
const document = {
|
|
138
|
+
userId: toObjectId(userId) || null,
|
|
139
|
+
config,
|
|
140
|
+
version: '0.0.0',
|
|
141
|
+
status: 'IN_CREATION',
|
|
142
|
+
entityIds: toObjectIdArray(entities),
|
|
143
|
+
messages: { errors: [], warnings: [], info: [], logs: [] },
|
|
144
|
+
errors: [],
|
|
145
|
+
warnings: [],
|
|
146
|
+
info: [],
|
|
147
|
+
logs: [],
|
|
148
|
+
createdAt: now,
|
|
149
|
+
updatedAt: now,
|
|
150
|
+
};
|
|
151
|
+
const insertedId = await insertOne(this.prisma, 'Integration', document);
|
|
152
|
+
const created = await findOne(this.prisma, 'Integration', { _id: insertedId });
|
|
153
|
+
if (!created) {
|
|
154
|
+
console.error('[IntegrationRepositoryDocumentDB] Integration not found after insert', {
|
|
155
|
+
insertedId: fromObjectId(insertedId),
|
|
156
|
+
userId,
|
|
157
|
+
config,
|
|
158
|
+
});
|
|
159
|
+
throw new Error(
|
|
160
|
+
'Failed to create integration: Document not found after insert. ' +
|
|
161
|
+
'This indicates a database consistency issue.'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return this._mapIntegration(created);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async findIntegrationByUserId(userId) {
|
|
168
|
+
const objectId = toObjectId(userId);
|
|
169
|
+
if (!objectId) return null;
|
|
170
|
+
const doc = await findOne(this.prisma, 'Integration', { userId: objectId });
|
|
171
|
+
return doc ? this._mapIntegration(doc) : null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async updateIntegrationConfig(integrationId, config) {
|
|
175
|
+
if (config === null || config === undefined) {
|
|
176
|
+
throw new Error('Config parameter is required');
|
|
177
|
+
}
|
|
178
|
+
const objectId = toObjectId(integrationId);
|
|
179
|
+
if (!objectId) {
|
|
180
|
+
throw new Error(`Integration with id ${integrationId} not found`);
|
|
181
|
+
}
|
|
182
|
+
await updateOne(
|
|
183
|
+
this.prisma,
|
|
184
|
+
'Integration',
|
|
185
|
+
{ _id: objectId },
|
|
186
|
+
{
|
|
187
|
+
$set: {
|
|
188
|
+
config,
|
|
189
|
+
updatedAt: new Date(),
|
|
190
|
+
},
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
const updated = await findOne(this.prisma, 'Integration', { _id: objectId });
|
|
194
|
+
if (!updated) {
|
|
195
|
+
console.error('[IntegrationRepositoryDocumentDB] Integration not found after update', {
|
|
196
|
+
integrationId: fromObjectId(objectId),
|
|
197
|
+
config,
|
|
198
|
+
});
|
|
199
|
+
throw new Error(
|
|
200
|
+
'Failed to update integration: Document not found after update. ' +
|
|
201
|
+
'This indicates a database consistency issue.'
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return this._mapIntegration(updated);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Atomically merge a patch into the existing config with a per-key
|
|
209
|
+
* $set (config.<k> for each patch key), then re-read to shape the
|
|
210
|
+
* return value — DocumentDB's raw update command doesn't return the
|
|
211
|
+
* post-update document directly.
|
|
212
|
+
*
|
|
213
|
+
* @param {string} integrationId - Integration ID
|
|
214
|
+
* @param {Object} patch - Keys to merge into the existing config
|
|
215
|
+
* @returns {Promise<Object>} Updated integration object
|
|
216
|
+
*/
|
|
217
|
+
async patchIntegrationConfig(integrationId, patch) {
|
|
218
|
+
validateConfigPatch(patch);
|
|
219
|
+
const objectId = toObjectId(integrationId);
|
|
220
|
+
if (!objectId) {
|
|
221
|
+
throw new Error(`Integration with id ${integrationId} not found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const $set = { updatedAt: new Date() };
|
|
225
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
226
|
+
$set[`config.${key}`] = value;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const result = await updateOne(
|
|
230
|
+
this.prisma,
|
|
231
|
+
'Integration',
|
|
232
|
+
{ _id: objectId },
|
|
233
|
+
{ $set }
|
|
234
|
+
);
|
|
235
|
+
if (result.writeErrors?.length) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`Failed to patch integration config: ${result.writeErrors[0].errmsg}`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
if (!result.n) {
|
|
241
|
+
throw new Error(`Integration with id ${integrationId} not found`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const updated = await findOne(this.prisma, 'Integration', { _id: objectId });
|
|
245
|
+
if (!updated) {
|
|
246
|
+
console.error('[IntegrationRepositoryDocumentDB] Integration not found after update', {
|
|
247
|
+
integrationId: fromObjectId(objectId),
|
|
248
|
+
patch,
|
|
249
|
+
});
|
|
250
|
+
throw new Error(
|
|
251
|
+
'Failed to update integration: Document not found after update. ' +
|
|
252
|
+
'This indicates a database consistency issue.'
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return this._mapIntegration(updated);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Drain the full cursor so a deployment-wide report is never truncated.
|
|
259
|
+
async findAllForReport({ status, userId } = {}) {
|
|
260
|
+
const filter = {};
|
|
261
|
+
if (status) filter.status = status;
|
|
262
|
+
if (userId !== undefined && userId !== null) {
|
|
263
|
+
const objectId = toObjectId(userId);
|
|
264
|
+
// Invalid userId means no matches — don't fall through to an unfiltered whole-deployment query.
|
|
265
|
+
if (!objectId) return [];
|
|
266
|
+
filter.userId = objectId;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const docs = await findManyDrained(this.prisma, 'Integration', filter);
|
|
270
|
+
|
|
271
|
+
return docs.map((doc) => {
|
|
272
|
+
const errors = this._extractReportErrors(doc);
|
|
273
|
+
return {
|
|
274
|
+
id: fromObjectId(doc?._id),
|
|
275
|
+
type: doc?.config?.type ?? null,
|
|
276
|
+
status: doc?.status ?? null,
|
|
277
|
+
userId: fromObjectId(doc?.userId) ?? null,
|
|
278
|
+
version: doc?.version ?? null,
|
|
279
|
+
errorCount: Array.isArray(errors) ? errors.length : 0,
|
|
280
|
+
moduleCount: Array.isArray(doc?.entityIds)
|
|
281
|
+
? doc.entityIds.length
|
|
282
|
+
: 0,
|
|
283
|
+
createdAt: doc?.createdAt ?? null,
|
|
284
|
+
updatedAt: doc?.updatedAt ?? null,
|
|
285
|
+
};
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
_extractReportErrors(doc) {
|
|
290
|
+
if (Array.isArray(doc?.errors)) return doc.errors;
|
|
291
|
+
if (Array.isArray(doc?.messages?.errors)) return doc.messages.errors;
|
|
292
|
+
return [];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
_mapIntegration(doc) {
|
|
296
|
+
const messages = this._extractMessages(doc);
|
|
297
|
+
return {
|
|
298
|
+
id: fromObjectId(doc?._id),
|
|
299
|
+
entitiesIds: (doc?.entityIds || []).map((value) => fromObjectId(value)),
|
|
300
|
+
userId: fromObjectId(doc?.userId),
|
|
301
|
+
config: doc?.config ?? null,
|
|
302
|
+
version: doc?.version ?? null,
|
|
303
|
+
status: doc?.status ?? null,
|
|
304
|
+
messages,
|
|
305
|
+
createdAt: doc?.createdAt ?? null,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
_extractMessages(doc) {
|
|
310
|
+
const base = doc?.messages && typeof doc.messages === 'object' ? doc.messages : {};
|
|
311
|
+
return {
|
|
312
|
+
errors: base.errors ?? doc?.errors ?? [],
|
|
313
|
+
warnings: base.warnings ?? doc?.warnings ?? [],
|
|
314
|
+
info: base.info ?? doc?.info ?? [],
|
|
315
|
+
logs: base.logs ?? doc?.logs ?? [],
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
module.exports = { IntegrationRepositoryDocumentDB };
|
|
321
|
+
|
|
322
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { IntegrationRepositoryMongo } = require('./integration-repository-mongo');
|
|
2
|
+
const { IntegrationRepositoryPostgres } = require('./integration-repository-postgres');
|
|
3
|
+
const {
|
|
4
|
+
IntegrationRepositoryDocumentDB,
|
|
5
|
+
} = require('./integration-repository-documentdb');
|
|
6
|
+
const config = require('../../database/config');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Integration Repository Factory
|
|
10
|
+
* Creates the appropriate repository adapter based on database type
|
|
11
|
+
*
|
|
12
|
+
* This implements the Factory pattern for Hexagonal Architecture:
|
|
13
|
+
* - Reads database type from app definition (backend/index.js)
|
|
14
|
+
* - Returns correct adapter (MongoDB or PostgreSQL)
|
|
15
|
+
* - Provides clear error for unsupported databases
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```javascript
|
|
19
|
+
* const repository = createIntegrationRepository();
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @returns {IntegrationRepositoryInterface} Configured repository adapter
|
|
23
|
+
* @throws {Error} If database type is not supported
|
|
24
|
+
*/
|
|
25
|
+
function createIntegrationRepository() {
|
|
26
|
+
const dbType = config.DB_TYPE;
|
|
27
|
+
|
|
28
|
+
switch (dbType) {
|
|
29
|
+
case 'mongodb':
|
|
30
|
+
return new IntegrationRepositoryMongo();
|
|
31
|
+
|
|
32
|
+
case 'postgresql':
|
|
33
|
+
return new IntegrationRepositoryPostgres();
|
|
34
|
+
|
|
35
|
+
case 'documentdb':
|
|
36
|
+
return new IntegrationRepositoryDocumentDB();
|
|
37
|
+
|
|
38
|
+
default:
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = {
|
|
46
|
+
createIntegrationRepository,
|
|
47
|
+
// Export adapters for direct testing
|
|
48
|
+
IntegrationRepositoryMongo,
|
|
49
|
+
IntegrationRepositoryPostgres,
|
|
50
|
+
IntegrationRepositoryDocumentDB,
|
|
51
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for integration persistence adapters
|
|
4
|
+
*
|
|
5
|
+
* This follows the Port in Hexagonal Architecture:
|
|
6
|
+
* - Domain layer depends on this abstraction
|
|
7
|
+
* - Concrete adapters (MongoDB, PostgreSQL) implement this interface
|
|
8
|
+
* - Use cases receive repositories via dependency injection
|
|
9
|
+
*
|
|
10
|
+
* @abstract
|
|
11
|
+
*/
|
|
12
|
+
class IntegrationRepositoryInterface {
|
|
13
|
+
/**
|
|
14
|
+
* Find all integrations for a user
|
|
15
|
+
*
|
|
16
|
+
* @param {string|number} userId - User ID
|
|
17
|
+
* @returns {Promise<Array>} Array of integration objects
|
|
18
|
+
* @abstract
|
|
19
|
+
*/
|
|
20
|
+
async findIntegrationsByUserId(userId) {
|
|
21
|
+
throw new Error('Method findIntegrationsByUserId must be implemented by subclass');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Find integrations, optionally filtered by config type and/or status.
|
|
26
|
+
* With no filter, returns every integration.
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} [filter={}]
|
|
29
|
+
* @param {string} [filter.type] - Integration type (config.type)
|
|
30
|
+
* @param {string} [filter.status] - Integration status
|
|
31
|
+
* @returns {Promise<Array>} Array of integration objects (possibly empty)
|
|
32
|
+
* @abstract
|
|
33
|
+
*/
|
|
34
|
+
async findIntegrations(filter = {}) {
|
|
35
|
+
throw new Error('Method findIntegrations must be implemented by subclass');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Find every integration in a report-shaped projection, optionally
|
|
40
|
+
* filtered by status and/or owning user. Adapters must drain the full
|
|
41
|
+
* result set (no first-batch truncation) since this powers a
|
|
42
|
+
* deployment-wide scan.
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} [filter={}]
|
|
45
|
+
* @param {string} [filter.status] - Integration status
|
|
46
|
+
* @param {string|number} [filter.userId] - Owning user ID
|
|
47
|
+
* @returns {Promise<Array<{id, type, status, userId, version, errorCount, moduleCount, createdAt, updatedAt}>>}
|
|
48
|
+
* @abstract
|
|
49
|
+
*/
|
|
50
|
+
async findAllForReport(filter = {}) {
|
|
51
|
+
throw new Error('Method findAllForReport must be implemented by subclass');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Delete integration by ID
|
|
56
|
+
*
|
|
57
|
+
* @param {string|number} integrationId - Integration ID
|
|
58
|
+
* @returns {Promise<Object>} Deletion result
|
|
59
|
+
* @abstract
|
|
60
|
+
*/
|
|
61
|
+
async deleteIntegrationById(integrationId) {
|
|
62
|
+
throw new Error('Method deleteIntegrationById must be implemented by subclass');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Find integration by name
|
|
67
|
+
*
|
|
68
|
+
* @param {string} name - Integration type name
|
|
69
|
+
* @returns {Promise<Object>} Integration object
|
|
70
|
+
* @abstract
|
|
71
|
+
*/
|
|
72
|
+
async findIntegrationByName(name) {
|
|
73
|
+
throw new Error('Method findIntegrationByName must be implemented by subclass');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Find integration by ID
|
|
78
|
+
*
|
|
79
|
+
* @param {string|number} id - Integration ID
|
|
80
|
+
* @returns {Promise<Object>} Integration object
|
|
81
|
+
* @abstract
|
|
82
|
+
*/
|
|
83
|
+
async findIntegrationById(id) {
|
|
84
|
+
throw new Error('Method findIntegrationById must be implemented by subclass');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Update integration status
|
|
89
|
+
*
|
|
90
|
+
* @param {string|number} integrationId - Integration ID
|
|
91
|
+
* @param {string} status - New status
|
|
92
|
+
* @returns {Promise<boolean>} Success indicator
|
|
93
|
+
* @abstract
|
|
94
|
+
*/
|
|
95
|
+
async updateIntegrationStatus(integrationId, status) {
|
|
96
|
+
throw new Error('Method updateIntegrationStatus must be implemented by subclass');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Update integration messages
|
|
101
|
+
*
|
|
102
|
+
* @param {string|number} integrationId - Integration ID
|
|
103
|
+
* @param {string} messageType - Type of message (errors, warnings, info, logs)
|
|
104
|
+
* @param {string} messageTitle - Message title
|
|
105
|
+
* @param {string} messageBody - Message body
|
|
106
|
+
* @param {Date} messageTimestamp - Message timestamp
|
|
107
|
+
* @returns {Promise<boolean>} Success indicator
|
|
108
|
+
* @abstract
|
|
109
|
+
*/
|
|
110
|
+
async updateIntegrationMessages(
|
|
111
|
+
integrationId,
|
|
112
|
+
messageType,
|
|
113
|
+
messageTitle,
|
|
114
|
+
messageBody,
|
|
115
|
+
messageTimestamp
|
|
116
|
+
) {
|
|
117
|
+
throw new Error('Method updateIntegrationMessages must be implemented by subclass');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a new integration
|
|
122
|
+
*
|
|
123
|
+
* @param {Array<string|number>} entities - Array of entity IDs
|
|
124
|
+
* @param {string|number} userId - User ID
|
|
125
|
+
* @param {Object} config - Integration configuration
|
|
126
|
+
* @returns {Promise<Object>} Created integration object
|
|
127
|
+
* @abstract
|
|
128
|
+
*/
|
|
129
|
+
async createIntegration(entities, userId, config) {
|
|
130
|
+
throw new Error('Method createIntegration must be implemented by subclass');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Find integration by user ID (returns single integration)
|
|
135
|
+
*
|
|
136
|
+
* @param {string|number} userId - User ID
|
|
137
|
+
* @returns {Promise<Object|null>} Integration object or null
|
|
138
|
+
* @abstract
|
|
139
|
+
*/
|
|
140
|
+
async findIntegrationByUserId(userId) {
|
|
141
|
+
throw new Error('Method findIntegrationByUserId must be implemented by subclass');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Update integration configuration
|
|
146
|
+
*
|
|
147
|
+
* @param {string|number} integrationId - Integration ID
|
|
148
|
+
* @param {Object} config - Updated configuration object
|
|
149
|
+
* @returns {Promise<Object>} Updated integration object
|
|
150
|
+
* @abstract
|
|
151
|
+
*/
|
|
152
|
+
async updateIntegrationConfig(integrationId, config) {
|
|
153
|
+
throw new Error('Method updateIntegrationConfig must be implemented by subclass');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Atomically merge a partial update into an integration's config. Keys
|
|
158
|
+
* not present in the patch are left untouched; concurrent patches with
|
|
159
|
+
* disjoint keys must both persist. Patch values may not be null or
|
|
160
|
+
* undefined — key deletion is only supported via updateIntegrationConfig.
|
|
161
|
+
*
|
|
162
|
+
* @param {string|number} integrationId - Integration ID
|
|
163
|
+
* @param {Object} patch - Keys to merge into the existing config
|
|
164
|
+
* @returns {Promise<Object>} Updated integration object
|
|
165
|
+
* @abstract
|
|
166
|
+
*/
|
|
167
|
+
async patchIntegrationConfig(integrationId, patch) {
|
|
168
|
+
throw new Error('Method patchIntegrationConfig must be implemented by subclass');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Find all integrations whose entity set includes the given entity ID.
|
|
173
|
+
*
|
|
174
|
+
* Used by the authorization callback flow to walk up from a re-authorized
|
|
175
|
+
* entity to its parent integrations so that any in a broken state (ERROR,
|
|
176
|
+
* DISABLED) can be restored to ENABLED.
|
|
177
|
+
*
|
|
178
|
+
* @param {string|number} entityId - Entity ID
|
|
179
|
+
* @returns {Promise<Array>} Array of integration objects (possibly empty)
|
|
180
|
+
* @abstract
|
|
181
|
+
*/
|
|
182
|
+
async findIntegrationsByEntityId(entityId) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
'Method findIntegrationsByEntityId must be implemented by subclass'
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = { IntegrationRepositoryInterface };
|