@friggframework/core 2.0.0--canary.690.08cd07e.0 → 2.0.0--canary.694.f66a64a.0
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 +0 -28
- package/README.md +0 -105
- package/application/commands/integration-commands.js +10 -20
- package/application/commands/scheduler-commands.js +7 -11
- package/application/commands/user-commands.js +5 -17
- package/application/index.js +2 -6
- package/core/Worker.js +7 -31
- package/core/create-handler.js +0 -9
- package/credential/repositories/credential-repository-documentdb.js +0 -34
- package/credential/repositories/credential-repository-interface.js +0 -15
- package/credential/repositories/credential-repository-mongo.js +0 -23
- package/credential/repositories/credential-repository-postgres.js +0 -28
- package/database/config.js +24 -48
- package/database/documentdb-utils.js +2 -2
- package/database/encryption/encryption-schema-registry.js +12 -93
- package/database/prisma.js +2 -4
- package/errors/index.js +4 -0
- package/errors/mapping-already-exists-error.js +14 -0
- package/generated/prisma-mongodb/edge.js +38 -33
- package/generated/prisma-mongodb/index-browser.js +35 -30
- package/generated/prisma-mongodb/index.d.ts +1880 -3191
- package/generated/prisma-mongodb/index.js +38 -33
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +50 -86
- package/generated/prisma-mongodb/wasm.js +38 -33
- package/generated/prisma-postgresql/edge.js +38 -33
- package/generated/prisma-postgresql/index-browser.js +35 -30
- package/generated/prisma-postgresql/index.d.ts +2050 -3390
- package/generated/prisma-postgresql/index.js +38 -33
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +48 -81
- package/generated/prisma-postgresql/wasm.js +38 -33
- package/handlers/WEBHOOKS.md +29 -0
- package/handlers/app-definition-loader.js +19 -128
- package/handlers/app-handler-helpers.js +3 -25
- package/handlers/backend-utils.js +25 -31
- package/handlers/middleware/admin-auth.js +1 -14
- package/handlers/routers/auth.js +10 -46
- package/handlers/routers/health.js +4 -13
- package/handlers/routers/integration-defined-routers.js +92 -144
- package/handlers/routers/integration-webhook-routers.js +64 -102
- package/handlers/workers/integration-defined-workers.js +2 -5
- package/handlers/workers/integration-triggers.js +25 -0
- package/index.js +3 -65
- package/infrastructure/scheduler/index.js +6 -19
- package/infrastructure/scheduler/recurrence.js +204 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +7 -55
- package/integrations/data-defined/README.md +185 -0
- package/integrations/data-defined/canonical.js +11 -0
- package/integrations/data-defined/capabilities/acmeerp.capabilities.json +608 -0
- package/integrations/data-defined/capabilities/asana.capabilities.json +265 -0
- package/integrations/data-defined/capabilities/calendly.capabilities.json +385 -0
- package/integrations/data-defined/capabilities/docusign.capabilities.json +314 -0
- package/integrations/data-defined/capabilities/fathom.capabilities.json +228 -0
- package/integrations/data-defined/capabilities/github.capabilities.json +563 -0
- package/integrations/data-defined/capabilities/hubspot.capabilities.json +715 -0
- package/integrations/data-defined/capabilities/jira.capabilities.json +376 -0
- package/integrations/data-defined/capabilities/klaviyo.capabilities.json +475 -0
- package/integrations/data-defined/capabilities/linear.capabilities.json +324 -0
- package/integrations/data-defined/capabilities/netsuite.capabilities.json +491 -0
- package/integrations/data-defined/capabilities/notion.capabilities.json +208 -0
- package/integrations/data-defined/capabilities/phone.capabilities.json +470 -0
- package/integrations/data-defined/capabilities/pipedrive.capabilities.json +388 -0
- package/integrations/data-defined/capabilities/quickbooks.capabilities.json +615 -0
- package/integrations/data-defined/capabilities/salesforce.capabilities.json +507 -0
- package/integrations/data-defined/capabilities/shopify.capabilities.json +1082 -0
- package/integrations/data-defined/capabilities/slack.capabilities.json +363 -0
- package/integrations/data-defined/capabilities/stripe.capabilities.json +580 -0
- package/integrations/data-defined/capabilities/webflow.capabilities.json +196 -0
- package/integrations/data-defined/capabilities/zendesk.capabilities.json +409 -0
- package/integrations/data-defined/compile.js +80 -0
- package/integrations/data-defined/config-form.js +137 -0
- package/integrations/data-defined/data-defined-integration.js +417 -0
- package/integrations/data-defined/examples/acme-erp-quickbooks.definition.json +467 -0
- package/integrations/data-defined/examples/asana-slack.definition.json +220 -0
- package/integrations/data-defined/examples/calendly-salesforce.definition.json +459 -0
- package/integrations/data-defined/examples/docusign-salesforce.definition.json +305 -0
- package/integrations/data-defined/examples/fathom-hubspot-notion.definition.json +575 -0
- package/integrations/data-defined/examples/github-linear.definition.json +316 -0
- package/integrations/data-defined/examples/hubspot-slack.definition.json +409 -0
- package/integrations/data-defined/examples/klaviyo-hubspot.definition.json +339 -0
- package/integrations/data-defined/examples/phone-hubspot.definition.json +637 -0
- package/integrations/data-defined/examples/pipedrive-hubspot.definition.json +136 -0
- package/integrations/data-defined/examples/pipedrive-phone.definition.json +340 -0
- package/integrations/data-defined/examples/records/phone-hubspot.definition-version.json +652 -0
- package/integrations/data-defined/examples/records/phone-hubspot.integration.json +86 -0
- package/integrations/data-defined/examples/records/phone-hubspot.mappings.json +39 -0
- package/integrations/data-defined/examples/records/phone-hubspot.workflow-run.json +62 -0
- package/integrations/data-defined/examples/shopify-klaviyo.definition.json +488 -0
- package/integrations/data-defined/examples/shopify-netsuite.definition.json +622 -0
- package/integrations/data-defined/examples/stripe-quickbooks.definition.json +476 -0
- package/integrations/data-defined/examples/webflow-hubspot-slack.definition.json +262 -0
- package/integrations/data-defined/examples/zendesk-jira.definition.json +604 -0
- package/integrations/data-defined/expressions.js +225 -0
- package/integrations/data-defined/index.js +39 -0
- package/integrations/data-defined/interpreter.js +89 -0
- package/integrations/data-defined/manifests.js +125 -0
- package/integrations/data-defined/repositories/definition-version-repository.js +67 -0
- package/integrations/data-defined/repositories/workflow-run-repository.js +59 -0
- package/integrations/data-defined/router.js +97 -0
- package/integrations/data-defined/runtime.js +208 -0
- package/integrations/data-defined/schema/capability-manifest.v0.1.schema.json +377 -0
- package/integrations/data-defined/schema/installation.v0.1.schema.json +130 -0
- package/integrations/data-defined/schema/integration-definition.v0.1.schema.json +902 -0
- package/integrations/data-defined/schema/records.md +98 -0
- package/integrations/data-defined/schema-check.js +58 -0
- package/integrations/data-defined/scripts/validate.js +66 -0
- package/integrations/data-defined/steps.js +89 -0
- package/integrations/data-defined/transforms.js +91 -0
- package/integrations/data-defined/use-cases/definition-use-cases.js +187 -0
- package/integrations/data-defined/validate.js +384 -0
- package/integrations/data-defined/versioning.js +176 -0
- package/integrations/data-defined/webhooks.js +119 -0
- package/integrations/index.js +0 -1
- package/integrations/integration-base.js +117 -0
- package/integrations/integration-router.js +101 -131
- package/integrations/repositories/integration-mapping-repository-documentdb.js +50 -0
- package/integrations/repositories/integration-mapping-repository-interface.js +15 -0
- package/integrations/repositories/integration-mapping-repository-mongo.js +29 -0
- package/integrations/repositories/integration-mapping-repository-postgres.js +30 -0
- package/integrations/repositories/integration-mapping-repository.js +29 -0
- package/integrations/repositories/integration-repository-documentdb.js +9 -37
- package/integrations/repositories/integration-repository-interface.js +4 -17
- package/integrations/repositories/integration-repository-mongo.js +96 -64
- package/integrations/repositories/integration-repository-postgres.js +81 -63
- package/integrations/repositories/process-repository-mongo.js +1 -1
- package/integrations/tests/doubles/test-integration-repository.js +1 -12
- package/integrations/triggers.js +244 -0
- package/integrations/use-cases/create-integration.js +20 -55
- package/integrations/use-cases/get-integrations-for-user.js +40 -80
- package/integrations/use-cases/index.js +1 -7
- package/integrations/use-cases/run-trigger-tick.js +132 -0
- package/integrations/use-cases/run-trigger.js +77 -0
- package/integrations/utils/map-integration-dto.js +14 -43
- package/modules/index.js +0 -14
- package/modules/module-factory.js +0 -12
- package/modules/module.js +2 -53
- package/modules/repositories/module-repository-documentdb.js +6 -51
- package/modules/repositories/module-repository-interface.js +2 -19
- package/modules/repositories/module-repository-mongo.js +74 -67
- package/modules/repositories/module-repository-postgres.js +74 -66
- package/modules/repositories/module-repository.js +1 -2
- package/modules/requester/requester.js +5 -35
- package/modules/use-cases/get-entities-for-user.js +13 -26
- package/modules/use-cases/get-entity-options-by-id.js +4 -10
- package/modules/use-cases/get-entity-options-by-type.js +1 -1
- package/modules/use-cases/get-module-instance-from-type.js +1 -1
- package/modules/use-cases/get-module.js +4 -10
- package/modules/use-cases/process-authorization-callback.js +19 -53
- package/modules/use-cases/refresh-entity-options.js +4 -10
- package/modules/use-cases/test-module-auth.js +4 -10
- package/package.json +6 -6
- package/prisma-mongodb/schema.prisma +50 -86
- package/prisma-postgresql/migrations/20261018000000_add_data_defined_integrations/migration.sql +66 -0
- package/prisma-postgresql/schema.prisma +48 -81
- package/queues/index.js +0 -25
- package/queues/queuer-util.js +9 -2
- package/types/index.d.ts +0 -2
- package/user/repositories/user-repository-documentdb.js +2 -27
- package/user/repositories/user-repository-interface.js +0 -18
- package/user/repositories/user-repository-mongo.js +0 -24
- package/user/repositories/user-repository-postgres.js +0 -18
- package/user/use-cases/authenticate-user.js +1 -7
- package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
- package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
- package/user/user.js +1 -64
- package/credential/use-cases/credential-operations-for-user.js +0 -202
- package/credential/use-cases/reauthorize-credential-for-user.js +0 -73
- package/database/organization-where.js +0 -18
- package/database/unique-violation.js +0 -25
- package/extensions/bootstrap-runner.js +0 -43
- package/extensions/extension-loader.js +0 -187
- package/extensions/index.js +0 -41
- package/extensions/initialize-app.js +0 -123
- package/extensions/route-mounter.js +0 -103
- package/extensions/schema-composer.js +0 -188
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +0 -216
- package/infrastructure/scheduler/scheduled-job-repository.js +0 -118
- package/integrations/repositories/integration-not-found.js +0 -14
- package/integrations/schedule-config.js +0 -80
- package/integrations/use-cases/dispatch-ongoing-syncs.js +0 -100
- package/integrations/use-cases/integration-operations-for-user.js +0 -256
- package/integrations/use-cases/resolve-integration-ownership.js +0 -177
- package/management-api/create-management-api-router.js +0 -49
- package/management-api/error-response.js +0 -116
- package/management-api/management-api-config.js +0 -151
- package/management-api/meta-router.js +0 -76
- package/management-api/openapi/build-openapi.js +0 -144
- package/management-api/openapi/components.js +0 -415
- package/management-api/openapi/v1-operations.js +0 -83
- package/management-api/openapi/v2-operations.js +0 -264
- package/management-api/route-registry.js +0 -411
- package/management-api/test-support/http-client.js +0 -39
- package/management-api/use-cases/get-management-api-meta.js +0 -57
- package/management-api/v1-deprecation.js +0 -120
- package/management-api/v2/create-v2-router.js +0 -85
- package/management-api/v2/dependencies.js +0 -281
- package/management-api/v2/dto.js +0 -143
- package/management-api/v2/handlers/authorization.js +0 -94
- package/management-api/v2/handlers/credentials.js +0 -33
- package/management-api/v2/handlers/entities.js +0 -77
- package/management-api/v2/handlers/integrations.js +0 -128
- package/management-api/v2/handlers/proxy.js +0 -34
- package/management-api/v2/request.js +0 -85
- package/management-api/v2/test-support/fake-dependencies.js +0 -103
- package/modules/domain/authorization-session.js +0 -144
- package/modules/entity-scope.js +0 -15
- package/modules/entity-type-registry.js +0 -311
- package/modules/proxy/proxy-bases.js +0 -169
- package/modules/proxy/proxy-errors.js +0 -31
- package/modules/proxy/proxy-path.js +0 -183
- package/modules/proxy/proxy-policy.js +0 -277
- package/modules/repositories/authorization-session-repository-documentdb.js +0 -112
- package/modules/repositories/authorization-session-repository-factory.js +0 -31
- package/modules/repositories/authorization-session-repository-interface.js +0 -47
- package/modules/repositories/authorization-session-repository-prisma.js +0 -87
- package/modules/repositories/entity-not-found.js +0 -18
- package/modules/requester/proxy-request.js +0 -245
- package/modules/scope-config.js +0 -192
- package/modules/scope-policy.js +0 -112
- package/modules/scope-resolution.js +0 -288
- package/modules/scope-visibility.js +0 -247
- package/modules/tests/doubles/in-memory-authorization-session-repository.js +0 -45
- package/modules/tests/doubles/ownership-matching.js +0 -18
- package/modules/use-cases/authorize-entity-for-user.js +0 -61
- package/modules/use-cases/create-entity-from-credential.js +0 -113
- package/modules/use-cases/entity-operations-for-user.js +0 -162
- package/modules/use-cases/entity-types.js +0 -139
- package/modules/use-cases/execute-entity-proxy-request.js +0 -331
- package/modules/use-cases/get-authorization-requirements.js +0 -100
- package/modules/use-cases/get-entity-module-for-user.js +0 -113
- package/modules/use-cases/manage-access.js +0 -21
- package/modules/use-cases/multi-step-authorization.js +0 -329
- package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +0 -28
- package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
- package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
- package/prisma-postgresql/migrations/20261017000000_add_scheduled_job/migration.sql +0 -28
- package/providers/index.js +0 -23
- package/providers/resolve-provider.js +0 -93
- package/providers/runtime-detection.js +0 -124
- package/queues/providers/index.js +0 -11
- package/queues/providers/netlify-background-provider.js +0 -150
- package/queues/providers/qstash-queue-provider.js +0 -219
- package/queues/providers/sqs-queue-provider.js +0 -70
- package/queues/queue-client-interface.js +0 -55
- package/queues/queue-message-auth.js +0 -193
- package/queues/queue-provider-factory.js +0 -101
- package/queues/queue-provider.js +0 -65
- package/queues/sqs-queue-client.js +0 -81
- package/types/modules/index.d.ts +0 -214
- package/types/user/index.d.ts +0 -134
- package/user/adopter-jwt-config.js +0 -177
- package/user/adopter-jwt-errors.js +0 -59
- package/user/adopter-token-verifier.js +0 -122
- package/user/app-user-helpers.js +0 -97
- package/user/create-user-authentication.js +0 -64
- package/user/membership.js +0 -51
- package/user/repositories/organization-membership-record.js +0 -19
- package/user/repositories/organization-membership-repository-documentdb.js +0 -106
- package/user/repositories/organization-membership-repository-factory.js +0 -42
- package/user/repositories/organization-membership-repository-interface.js +0 -57
- package/user/repositories/organization-membership-repository-mongo.js +0 -13
- package/user/repositories/organization-membership-repository-postgres.js +0 -29
- package/user/repositories/organization-membership-repository-prisma.js +0 -81
- package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
- package/user/use-cases/ensure-organization-membership.js +0 -92
- package/user/use-cases/find-individual-users-by-organization.js +0 -54
|
@@ -31,6 +31,9 @@ const {
|
|
|
31
31
|
GetIntegrationInstance,
|
|
32
32
|
} = require('./use-cases/get-integration-instance');
|
|
33
33
|
const { UpdateIntegration } = require('./use-cases/update-integration');
|
|
34
|
+
const {
|
|
35
|
+
getModulesDefinitionFromIntegrationClasses,
|
|
36
|
+
} = require('./utils/map-integration-dto');
|
|
34
37
|
const {
|
|
35
38
|
GetModuleInstanceFromType,
|
|
36
39
|
} = require('../modules/use-cases/get-module-instance-from-type');
|
|
@@ -51,51 +54,47 @@ const {
|
|
|
51
54
|
const {
|
|
52
55
|
createUserRepository,
|
|
53
56
|
} = require('../user/repositories/user-repository-factory');
|
|
57
|
+
const {
|
|
58
|
+
GetUserFromBearerToken,
|
|
59
|
+
} = require('../user/use-cases/get-user-from-bearer-token');
|
|
60
|
+
const {
|
|
61
|
+
GetUserFromXFriggHeaders,
|
|
62
|
+
} = require('../user/use-cases/get-user-from-x-frigg-headers');
|
|
63
|
+
const {
|
|
64
|
+
GetUserFromAdopterJwt,
|
|
65
|
+
} = require('../user/use-cases/get-user-from-adopter-jwt');
|
|
54
66
|
const {
|
|
55
67
|
AuthenticateWithSharedSecret,
|
|
56
68
|
} = require('../user/use-cases/authenticate-with-shared-secret');
|
|
57
69
|
const { AuthenticateUser } = require('../user/use-cases/authenticate-user');
|
|
58
|
-
const {
|
|
59
|
-
buildUserAuthentication,
|
|
60
|
-
} = require('../user/create-user-authentication');
|
|
61
70
|
const {
|
|
62
71
|
ProcessAuthorizationCallback,
|
|
63
72
|
} = require('../modules/use-cases/process-authorization-callback');
|
|
64
|
-
const { createScopePolicy } = require('../modules/scope-policy');
|
|
65
|
-
const {
|
|
66
|
-
AuthorizeEntityForUser,
|
|
67
|
-
} = require('../modules/use-cases/authorize-entity-for-user');
|
|
68
|
-
const {
|
|
69
|
-
CreateEntityFromCredential,
|
|
70
|
-
} = require('../modules/use-cases/create-entity-from-credential');
|
|
71
|
-
const {
|
|
72
|
-
ResolveIntegrationOwnership,
|
|
73
|
-
} = require('./use-cases/resolve-integration-ownership');
|
|
74
|
-
const { GetOwnedIntegrationRecord } = require('./use-cases/integration-operations-for-user');
|
|
75
73
|
|
|
76
74
|
const log = getLogger('frigg.integrations');
|
|
77
75
|
|
|
78
76
|
function createIntegrationRouter() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const {
|
|
82
|
-
integrations: integrationClasses,
|
|
83
|
-
userConfig,
|
|
84
|
-
moduleDefinitions,
|
|
85
|
-
ownership,
|
|
86
|
-
entityTypeRegistry,
|
|
87
|
-
} = loadAppDefinition();
|
|
88
|
-
// Ownership by scope (ADR-056 §3): one object every use case asks.
|
|
89
|
-
const scopePolicy = createScopePolicy({ ownership, entityTypeRegistry });
|
|
77
|
+
const { integrations: integrationClasses, userConfig } =
|
|
78
|
+
loadAppDefinition();
|
|
90
79
|
const moduleRepository = createModuleRepository();
|
|
91
80
|
const integrationRepository = createIntegrationRepository();
|
|
92
81
|
const credentialRepository = createCredentialRepository();
|
|
93
82
|
const userRepository = createUserRepository();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
83
|
+
|
|
84
|
+
const getUserFromBearerToken = new GetUserFromBearerToken({
|
|
85
|
+
userRepository,
|
|
86
|
+
userConfig,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const getUserFromXFriggHeaders = new GetUserFromXFriggHeaders({
|
|
90
|
+
userRepository,
|
|
91
|
+
userConfig,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const getUserFromAdopterJwt = new GetUserFromAdopterJwt({
|
|
95
|
+
userRepository,
|
|
96
|
+
userConfig,
|
|
97
|
+
});
|
|
99
98
|
|
|
100
99
|
const authenticateWithSharedSecret = new AuthenticateWithSharedSecret();
|
|
101
100
|
|
|
@@ -109,7 +108,8 @@ function createIntegrationRouter() {
|
|
|
109
108
|
|
|
110
109
|
const moduleFactory = new ModuleFactory({
|
|
111
110
|
moduleRepository,
|
|
112
|
-
moduleDefinitions
|
|
111
|
+
moduleDefinitions:
|
|
112
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
113
113
|
});
|
|
114
114
|
const deleteIntegrationForUser = new DeleteIntegrationForUser({
|
|
115
115
|
integrationRepository,
|
|
@@ -122,19 +122,6 @@ function createIntegrationRouter() {
|
|
|
122
122
|
integrationClasses,
|
|
123
123
|
moduleFactory,
|
|
124
124
|
moduleRepository,
|
|
125
|
-
scopePolicy,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// Decides who owns a new integration and which entities the caller may bind
|
|
129
|
-
// (the v1 create used to check neither), and who may reach an existing one.
|
|
130
|
-
const resolveIntegrationOwnership = new ResolveIntegrationOwnership({
|
|
131
|
-
moduleRepository,
|
|
132
|
-
integrationClasses,
|
|
133
|
-
scopePolicy,
|
|
134
|
-
});
|
|
135
|
-
const getOwnedIntegrationRecord = new GetOwnedIntegrationRecord({
|
|
136
|
-
integrationRepository,
|
|
137
|
-
scopePolicy,
|
|
138
125
|
});
|
|
139
126
|
|
|
140
127
|
const getCredentialForUser = new GetCredentialForUser({
|
|
@@ -149,8 +136,8 @@ function createIntegrationRouter() {
|
|
|
149
136
|
|
|
150
137
|
const getEntitiesForUser = new GetEntitiesForUser({
|
|
151
138
|
moduleRepository,
|
|
152
|
-
moduleDefinitions
|
|
153
|
-
|
|
139
|
+
moduleDefinitions:
|
|
140
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
154
141
|
});
|
|
155
142
|
|
|
156
143
|
const getIntegrationInstance = new GetIntegrationInstance({
|
|
@@ -166,65 +153,54 @@ function createIntegrationRouter() {
|
|
|
166
153
|
});
|
|
167
154
|
|
|
168
155
|
const getModuleInstanceFromType = new GetModuleInstanceFromType({
|
|
169
|
-
moduleDefinitions
|
|
156
|
+
moduleDefinitions:
|
|
157
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
170
158
|
});
|
|
171
159
|
|
|
172
160
|
const getEntityOptionsByType = new GetEntityOptionsByType({
|
|
173
|
-
moduleDefinitions
|
|
161
|
+
moduleDefinitions:
|
|
162
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
174
163
|
});
|
|
175
164
|
|
|
176
165
|
const testModuleAuth = new TestModuleAuth({
|
|
177
166
|
moduleRepository,
|
|
178
|
-
moduleDefinitions
|
|
179
|
-
|
|
167
|
+
moduleDefinitions:
|
|
168
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
180
169
|
});
|
|
181
170
|
|
|
182
171
|
const getModule = new GetModule({
|
|
183
172
|
moduleRepository,
|
|
184
|
-
moduleDefinitions
|
|
185
|
-
|
|
173
|
+
moduleDefinitions:
|
|
174
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
186
175
|
});
|
|
187
176
|
|
|
188
177
|
const getEntityOptionsById = new GetEntityOptionsById({
|
|
189
178
|
moduleRepository,
|
|
190
|
-
moduleDefinitions
|
|
191
|
-
|
|
179
|
+
moduleDefinitions:
|
|
180
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
192
181
|
});
|
|
193
182
|
|
|
194
183
|
const refreshEntityOptions = new RefreshEntityOptions({
|
|
195
184
|
moduleRepository,
|
|
196
|
-
moduleDefinitions
|
|
197
|
-
|
|
185
|
+
moduleDefinitions:
|
|
186
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
198
187
|
});
|
|
199
188
|
|
|
200
189
|
const getPossibleIntegrations = new GetPossibleIntegrations({
|
|
201
190
|
integrationClasses,
|
|
202
191
|
});
|
|
203
192
|
|
|
204
|
-
// The owner of what an authorization creates follows its scope (ADR-056 §3.2).
|
|
205
193
|
const processAuthorizationCallback = new ProcessAuthorizationCallback({
|
|
206
194
|
moduleRepository,
|
|
207
195
|
credentialRepository,
|
|
208
196
|
integrationRepository,
|
|
209
|
-
moduleDefinitions
|
|
210
|
-
|
|
211
|
-
const authorizeEntityForUser = new AuthorizeEntityForUser({
|
|
212
|
-
scopePolicy,
|
|
213
|
-
processAuthorizationCallback,
|
|
214
|
-
});
|
|
215
|
-
// v1 POST /api/entity: same owner resolution as /api/authorize.
|
|
216
|
-
const createEntityFromCredential = new CreateEntityFromCredential({
|
|
217
|
-
authorizeEntityForUser,
|
|
218
|
-
processAuthorizationCallback,
|
|
219
|
-
credentialRepository,
|
|
220
|
-
moduleDefinitions,
|
|
197
|
+
moduleDefinitions:
|
|
198
|
+
getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
221
199
|
});
|
|
222
200
|
|
|
223
201
|
const router = express();
|
|
224
202
|
|
|
225
203
|
setIntegrationRoutes(router, authenticateUser, {
|
|
226
|
-
resolveIntegrationOwnership,
|
|
227
|
-
getOwnedIntegrationRecord,
|
|
228
204
|
createIntegration,
|
|
229
205
|
deleteIntegrationForUser,
|
|
230
206
|
getIntegrationsForUser,
|
|
@@ -233,6 +209,11 @@ function createIntegrationRouter() {
|
|
|
233
209
|
updateIntegration,
|
|
234
210
|
getPossibleIntegrations,
|
|
235
211
|
});
|
|
212
|
+
// Data-defined integrations (ADR-063): only mounted when the app registers a data-defined class.
|
|
213
|
+
require('./data-defined/router').setDataDefinedRoutes(router, authenticateUser, {
|
|
214
|
+
getIntegrationInstance,
|
|
215
|
+
integrationClasses,
|
|
216
|
+
});
|
|
236
217
|
setEntityRoutes(router, authenticateUser, {
|
|
237
218
|
getCredentialForUser,
|
|
238
219
|
getModuleInstanceFromType,
|
|
@@ -241,8 +222,7 @@ function createIntegrationRouter() {
|
|
|
241
222
|
getModule,
|
|
242
223
|
getEntityOptionsById,
|
|
243
224
|
refreshEntityOptions,
|
|
244
|
-
|
|
245
|
-
createEntityFromCredential,
|
|
225
|
+
processAuthorizationCallback,
|
|
246
226
|
});
|
|
247
227
|
return router;
|
|
248
228
|
}
|
|
@@ -279,8 +259,6 @@ function checkRequiredParams(params, requiredKeys) {
|
|
|
279
259
|
*/
|
|
280
260
|
function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
281
261
|
const {
|
|
282
|
-
resolveIntegrationOwnership,
|
|
283
|
-
getOwnedIntegrationRecord,
|
|
284
262
|
createIntegration,
|
|
285
263
|
deleteIntegrationForUser,
|
|
286
264
|
getIntegrationsForUser,
|
|
@@ -289,22 +267,15 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
289
267
|
updateIntegration,
|
|
290
268
|
getPossibleIntegrations,
|
|
291
269
|
} = useCases;
|
|
292
|
-
|
|
293
|
-
// The owner of an integration the caller may reach (404 otherwise), which is
|
|
294
|
-
// what the id-and-owner use cases below expect. `manage: true` is for
|
|
295
|
-
// changing or deleting: an organization's integration needs an admin (403).
|
|
296
|
-
const ownerOf = async (integrationId, user, options) =>
|
|
297
|
-
(await getOwnedIntegrationRecord.execute(integrationId, user, options))
|
|
298
|
-
.userId;
|
|
299
|
-
|
|
300
270
|
router.route('/api/integrations').get(
|
|
301
271
|
catchAsyncError(async (req, res) => {
|
|
302
272
|
const user = await authenticateUser.execute(req);
|
|
303
|
-
const
|
|
273
|
+
const userId = user.getId();
|
|
274
|
+
const integrations = await getIntegrationsForUser.execute(userId);
|
|
304
275
|
const results = {
|
|
305
276
|
entities: {
|
|
306
277
|
options: await getPossibleIntegrations.execute(),
|
|
307
|
-
authorized: await getEntitiesForUser.execute(
|
|
278
|
+
authorized: await getEntitiesForUser.execute(userId),
|
|
308
279
|
},
|
|
309
280
|
integrations: integrations,
|
|
310
281
|
};
|
|
@@ -316,6 +287,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
316
287
|
router.route('/api/integrations').post(
|
|
317
288
|
catchAsyncError(async (req, res) => {
|
|
318
289
|
const user = await authenticateUser.execute(req);
|
|
290
|
+
const userId = user.getId();
|
|
319
291
|
const params = checkRequiredParams(req.body, [
|
|
320
292
|
'entities',
|
|
321
293
|
'config',
|
|
@@ -323,17 +295,10 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
323
295
|
|
|
324
296
|
get(params.config, 'type');
|
|
325
297
|
|
|
326
|
-
const { ownerId, organizationId, adoptUnscoped } =
|
|
327
|
-
await resolveIntegrationOwnership.execute({
|
|
328
|
-
entityIds: params.entities,
|
|
329
|
-
config: params.config,
|
|
330
|
-
user,
|
|
331
|
-
});
|
|
332
298
|
const integration = await createIntegration.execute(
|
|
333
299
|
params.entities,
|
|
334
|
-
|
|
335
|
-
params.config
|
|
336
|
-
{ organizationId, adoptUnscoped }
|
|
300
|
+
userId,
|
|
301
|
+
params.config
|
|
337
302
|
);
|
|
338
303
|
|
|
339
304
|
res.status(201).json(integration);
|
|
@@ -343,11 +308,12 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
343
308
|
router.route('/api/integrations/:integrationId').patch(
|
|
344
309
|
catchAsyncError(async (req, res) => {
|
|
345
310
|
const user = await authenticateUser.execute(req);
|
|
311
|
+
const userId = user.getId();
|
|
346
312
|
const params = checkRequiredParams(req.body, ['config']);
|
|
347
313
|
|
|
348
314
|
const integration = await updateIntegration.execute(
|
|
349
315
|
req.params.integrationId,
|
|
350
|
-
|
|
316
|
+
userId,
|
|
351
317
|
params.config
|
|
352
318
|
);
|
|
353
319
|
res.json(integration);
|
|
@@ -360,7 +326,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
360
326
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
361
327
|
await deleteIntegrationForUser.execute(
|
|
362
328
|
params.integrationId,
|
|
363
|
-
|
|
329
|
+
user.getId()
|
|
364
330
|
);
|
|
365
331
|
res.status(204).json({});
|
|
366
332
|
})
|
|
@@ -372,7 +338,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
372
338
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
373
339
|
const integration = await getIntegrationInstance.execute(
|
|
374
340
|
params.integrationId,
|
|
375
|
-
|
|
341
|
+
user.getId()
|
|
376
342
|
);
|
|
377
343
|
res.json(await integration.send('GET_CONFIG_OPTIONS'));
|
|
378
344
|
})
|
|
@@ -388,7 +354,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
388
354
|
]);
|
|
389
355
|
const integration = await getIntegrationInstance.execute(
|
|
390
356
|
params.integrationId,
|
|
391
|
-
|
|
357
|
+
user.getId()
|
|
392
358
|
);
|
|
393
359
|
|
|
394
360
|
res.json(
|
|
@@ -402,7 +368,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
402
368
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
403
369
|
const integration = await getIntegrationInstance.execute(
|
|
404
370
|
params.integrationId,
|
|
405
|
-
|
|
371
|
+
user.getId()
|
|
406
372
|
);
|
|
407
373
|
res.json(await integration.send('GET_USER_ACTIONS', req.body));
|
|
408
374
|
})
|
|
@@ -419,7 +385,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
419
385
|
]);
|
|
420
386
|
const integration = await getIntegrationInstance.execute(
|
|
421
387
|
params.integrationId,
|
|
422
|
-
|
|
388
|
+
user.getId()
|
|
423
389
|
);
|
|
424
390
|
|
|
425
391
|
res.json(
|
|
@@ -444,7 +410,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
444
410
|
]);
|
|
445
411
|
const integration = await getIntegrationInstance.execute(
|
|
446
412
|
params.integrationId,
|
|
447
|
-
|
|
413
|
+
user.getId()
|
|
448
414
|
);
|
|
449
415
|
|
|
450
416
|
res.json(
|
|
@@ -465,7 +431,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
465
431
|
]);
|
|
466
432
|
const integration = await getIntegrationInstance.execute(
|
|
467
433
|
params.integrationId,
|
|
468
|
-
|
|
434
|
+
user.getId()
|
|
469
435
|
);
|
|
470
436
|
res.json(await integration.send(params.actionId, req.body));
|
|
471
437
|
})
|
|
@@ -482,7 +448,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
482
448
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
483
449
|
const integration = await getIntegrationInstance.execute(
|
|
484
450
|
params.integrationId,
|
|
485
|
-
|
|
451
|
+
user.getId()
|
|
486
452
|
);
|
|
487
453
|
|
|
488
454
|
// We could perhaps augment router with dynamic options? Haven't decided yet, but here may be the place
|
|
@@ -502,7 +468,7 @@ function setIntegrationRoutes(router, authenticateUser, useCases) {
|
|
|
502
468
|
const params = checkRequiredParams(req.params, ['integrationId']);
|
|
503
469
|
const instance = await getIntegrationInstance.execute(
|
|
504
470
|
params.integrationId,
|
|
505
|
-
|
|
471
|
+
user.getId()
|
|
506
472
|
);
|
|
507
473
|
|
|
508
474
|
if (!instance) {
|
|
@@ -540,21 +506,16 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
540
506
|
getModule,
|
|
541
507
|
getEntityOptionsById,
|
|
542
508
|
refreshEntityOptions,
|
|
543
|
-
|
|
544
|
-
createEntityFromCredential,
|
|
509
|
+
processAuthorizationCallback,
|
|
545
510
|
} = useCases;
|
|
546
511
|
|
|
547
512
|
router.route('/api/authorize').get(
|
|
548
513
|
catchAsyncError(async (req, res) => {
|
|
549
514
|
const user = await authenticateUser.execute(req);
|
|
515
|
+
const userId = user.getId();
|
|
550
516
|
const params = checkRequiredParams(req.query, ['entityType']);
|
|
551
|
-
// The owner POST stores under, so GET and POST describe one connection.
|
|
552
|
-
const { ownerId } = authorizeEntityForUser.resolveOwnership({
|
|
553
|
-
user,
|
|
554
|
-
entityType: params.entityType,
|
|
555
|
-
});
|
|
556
517
|
const module = await getModuleInstanceFromType.execute(
|
|
557
|
-
|
|
518
|
+
userId,
|
|
558
519
|
params.entityType,
|
|
559
520
|
{ state: req.query.state }
|
|
560
521
|
);
|
|
@@ -573,15 +534,11 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
573
534
|
router.route('/api/authorize').post(
|
|
574
535
|
catchAsyncError(async (req, res) => {
|
|
575
536
|
const user = await authenticateUser.execute(req);
|
|
537
|
+
const userId = user.getId();
|
|
576
538
|
const params = checkRequiredParams(req.body, [
|
|
577
539
|
'entityType',
|
|
578
540
|
'data',
|
|
579
541
|
]);
|
|
580
|
-
const ownership = authorizeEntityForUser.resolveOwnership({
|
|
581
|
-
user,
|
|
582
|
-
entityType: params.entityType,
|
|
583
|
-
});
|
|
584
|
-
const userId = ownership.ownerId;
|
|
585
542
|
|
|
586
543
|
const dataKeys =
|
|
587
544
|
params.data && typeof params.data === 'object'
|
|
@@ -593,13 +550,11 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
593
550
|
dataKeys,
|
|
594
551
|
});
|
|
595
552
|
|
|
596
|
-
const
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
ownership,
|
|
602
|
-
});
|
|
553
|
+
const entityDetails = await processAuthorizationCallback.execute(
|
|
554
|
+
userId,
|
|
555
|
+
params.entityType,
|
|
556
|
+
params.data
|
|
557
|
+
);
|
|
603
558
|
|
|
604
559
|
log.info('Entity authorized', {
|
|
605
560
|
eventName: 'frigg.integrations.authorized',
|
|
@@ -616,20 +571,35 @@ function setEntityRoutes(router, authenticateUser, useCases) {
|
|
|
616
571
|
router.route('/api/entity').post(
|
|
617
572
|
catchAsyncError(async (req, res) => {
|
|
618
573
|
const user = await authenticateUser.execute(req);
|
|
574
|
+
const userId = user.getId();
|
|
619
575
|
const params = checkRequiredParams(req.body, [
|
|
620
576
|
'entityType',
|
|
621
577
|
'data',
|
|
622
578
|
]);
|
|
623
579
|
checkRequiredParams(req.body.data, ['credential_id']);
|
|
624
580
|
|
|
625
|
-
//
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
581
|
+
// May want to pass along the user ID as well so credential ID's can't be fished???
|
|
582
|
+
const credential = await getCredentialForUser.execute(
|
|
583
|
+
params.data.credential_id,
|
|
584
|
+
userId
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
if (!credential) {
|
|
588
|
+
throw Boom.badRequest('Invalid credential ID');
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const module = await getModuleInstanceFromType.execute(
|
|
592
|
+
userId,
|
|
593
|
+
params.entityType
|
|
594
|
+
);
|
|
595
|
+
const entityDetails = await module.getEntityDetails(
|
|
596
|
+
module.api,
|
|
597
|
+
null,
|
|
598
|
+
null,
|
|
599
|
+
userId
|
|
632
600
|
);
|
|
601
|
+
|
|
602
|
+
res.json(await module.findOrCreateEntity(entityDetails));
|
|
633
603
|
})
|
|
634
604
|
);
|
|
635
605
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const { MappingAlreadyExistsError } = require('../../errors');
|
|
2
3
|
const {
|
|
3
4
|
toObjectId,
|
|
4
5
|
fromObjectId,
|
|
@@ -180,6 +181,55 @@ class IntegrationMappingRepositoryDocumentDB extends IntegrationMappingRepositor
|
|
|
180
181
|
return this._mapMapping(decryptedMapping);
|
|
181
182
|
}
|
|
182
183
|
|
|
184
|
+
async createMapping(integrationId, sourceId, mapping) {
|
|
185
|
+
const now = new Date();
|
|
186
|
+
const encryptedDocument = await this.encryptionService.encryptFields(
|
|
187
|
+
'IntegrationMapping',
|
|
188
|
+
{
|
|
189
|
+
integrationId,
|
|
190
|
+
sourceId:
|
|
191
|
+
sourceId === null || sourceId === undefined
|
|
192
|
+
? null
|
|
193
|
+
: String(sourceId),
|
|
194
|
+
mapping,
|
|
195
|
+
createdAt: now,
|
|
196
|
+
updatedAt: now,
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
let insertedId;
|
|
201
|
+
try {
|
|
202
|
+
insertedId = await insertOne(
|
|
203
|
+
this.prisma,
|
|
204
|
+
'IntegrationMapping',
|
|
205
|
+
encryptedDocument
|
|
206
|
+
);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (error.code === 11000) {
|
|
209
|
+
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
210
|
+
cause: error,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const created = await findOne(this.prisma, 'IntegrationMapping', {
|
|
217
|
+
_id: insertedId,
|
|
218
|
+
});
|
|
219
|
+
if (!created) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
'Failed to create mapping: Document not found after insert. ' +
|
|
222
|
+
'This indicates a database consistency issue.'
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
return this._mapMapping(
|
|
226
|
+
await this.encryptionService.decryptFields(
|
|
227
|
+
'IntegrationMapping',
|
|
228
|
+
created
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
183
233
|
async findMappingsByIntegration(integrationId) {
|
|
184
234
|
const filter = {};
|
|
185
235
|
if (integrationId) filter.integrationId = integrationId;
|
|
@@ -39,6 +39,21 @@ class IntegrationMappingRepositoryInterface {
|
|
|
39
39
|
throw new Error('Method upsertMapping must be implemented by subclass');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Insert a mapping, failing if one already exists for the
|
|
44
|
+
* (integrationId, sourceId) pair. Atomic: usable as a claim/lock row.
|
|
45
|
+
*
|
|
46
|
+
* @param {string|number} integrationId - The integration ID
|
|
47
|
+
* @param {string} sourceId - The source ID for lookup
|
|
48
|
+
* @param {Object} mapping - The mapping data
|
|
49
|
+
* @returns {Promise<Object>} The created mapping document
|
|
50
|
+
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
51
|
+
* @abstract
|
|
52
|
+
*/
|
|
53
|
+
async createMapping(integrationId, sourceId, mapping) {
|
|
54
|
+
throw new Error('createMapping must be implemented by subclass');
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
/**
|
|
43
58
|
* Find all mappings for an integration
|
|
44
59
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const { MappingAlreadyExistsError } = require('../../errors');
|
|
2
3
|
const {
|
|
3
4
|
assertMappingWrittenUnencrypted,
|
|
4
5
|
decryptQueriedMappings,
|
|
@@ -93,6 +94,34 @@ class IntegrationMappingRepositoryMongo extends IntegrationMappingRepositoryInte
|
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Insert a mapping; fails if (integrationId, sourceId) already exists
|
|
99
|
+
*
|
|
100
|
+
* @param {string} integrationId - The integration ID
|
|
101
|
+
* @param {string} sourceId - The source ID
|
|
102
|
+
* @param {Object} mapping - The mapping data
|
|
103
|
+
* @returns {Promise<Object>} The created mapping document
|
|
104
|
+
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
105
|
+
*/
|
|
106
|
+
async createMapping(integrationId, sourceId, mapping) {
|
|
107
|
+
try {
|
|
108
|
+
return await this.prisma.integrationMapping.create({
|
|
109
|
+
data: {
|
|
110
|
+
integrationId,
|
|
111
|
+
sourceId: this._toString(sourceId),
|
|
112
|
+
mapping,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (error.code === 'P2002') {
|
|
117
|
+
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
118
|
+
cause: error,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
96
125
|
/**
|
|
97
126
|
* Find all mappings for an integration
|
|
98
127
|
* Replaces: IntegrationMapping.find({ integration: integrationId })
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const { MappingAlreadyExistsError } = require('../../errors');
|
|
2
3
|
const {
|
|
3
4
|
assertMappingWrittenUnencrypted,
|
|
4
5
|
decryptQueriedMappings,
|
|
@@ -150,6 +151,35 @@ class IntegrationMappingRepositoryPostgres extends IntegrationMappingRepositoryI
|
|
|
150
151
|
return this._convertMappingIds(result);
|
|
151
152
|
}
|
|
152
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Insert a mapping; fails if (integrationId, sourceId) already exists
|
|
156
|
+
*
|
|
157
|
+
* @param {string} integrationId - The integration ID
|
|
158
|
+
* @param {string} sourceId - The source ID
|
|
159
|
+
* @param {Object} mapping - The mapping data
|
|
160
|
+
* @returns {Promise<Object>} The created mapping document
|
|
161
|
+
* @throws {MappingAlreadyExistsError} If the pair already exists
|
|
162
|
+
*/
|
|
163
|
+
async createMapping(integrationId, sourceId, mapping) {
|
|
164
|
+
try {
|
|
165
|
+
const created = await this.prisma.integrationMapping.create({
|
|
166
|
+
data: {
|
|
167
|
+
integrationId: this._stringToInt(integrationId),
|
|
168
|
+
sourceId: this._toString(sourceId),
|
|
169
|
+
mapping,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
return this._convertMappingIds(created);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (error.code === 'P2002') {
|
|
175
|
+
throw new MappingAlreadyExistsError(integrationId, sourceId, {
|
|
176
|
+
cause: error,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
153
183
|
/**
|
|
154
184
|
* Find all mappings for an integration
|
|
155
185
|
* Replaces: IntegrationMapping.find({ integration: integrationId })
|