@shipfox/api-integration-core 2.0.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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +264 -0
- package/LICENSE +21 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-tool-selection.d.ts +15 -0
- package/dist/core/agent-tool-selection.d.ts.map +1 -0
- package/dist/core/agent-tool-selection.js +48 -0
- package/dist/core/agent-tool-selection.js.map +1 -0
- package/dist/core/entities/connection.d.ts +2 -0
- package/dist/core/entities/connection.d.ts.map +1 -0
- package/dist/core/entities/connection.js +3 -0
- package/dist/core/entities/connection.js.map +1 -0
- package/dist/core/entities/provider.d.ts +6 -0
- package/dist/core/entities/provider.d.ts.map +1 -0
- package/dist/core/entities/provider.js +3 -0
- package/dist/core/entities/provider.js.map +1 -0
- package/dist/core/errors.d.ts +29 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +40 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/providers/agent-tools.d.ts +2 -0
- package/dist/core/providers/agent-tools.d.ts.map +1 -0
- package/dist/core/providers/agent-tools.js +3 -0
- package/dist/core/providers/agent-tools.js.map +1 -0
- package/dist/core/providers/redact-checkout-spec.d.ts +9 -0
- package/dist/core/providers/redact-checkout-spec.d.ts.map +1 -0
- package/dist/core/providers/redact-checkout-spec.js +25 -0
- package/dist/core/providers/redact-checkout-spec.js.map +1 -0
- package/dist/core/providers/registry.d.ts +9 -0
- package/dist/core/providers/registry.d.ts.map +1 -0
- package/dist/core/providers/registry.js +52 -0
- package/dist/core/providers/registry.js.map +1 -0
- package/dist/core/providers/source-control.d.ts +2 -0
- package/dist/core/providers/source-control.d.ts.map +1 -0
- package/dist/core/providers/source-control.js +3 -0
- package/dist/core/providers/source-control.js.map +1 -0
- package/dist/core/source-control-service.d.ts +46 -0
- package/dist/core/source-control-service.d.ts.map +1 -0
- package/dist/core/source-control-service.js +84 -0
- package/dist/core/source-control-service.js.map +1 -0
- package/dist/db/connections.d.ts +67 -0
- package/dist/db/connections.d.ts.map +1 -0
- package/dist/db/connections.js +130 -0
- package/dist/db/connections.js.map +1 -0
- package/dist/db/db.d.ts +865 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +22 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/migrations.d.ts +2 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +5 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/connections.d.ts +165 -0
- package/dist/db/schema/connections.d.ts.map +1 -0
- package/dist/db/schema/connections.js +37 -0
- package/dist/db/schema/connections.js.map +1 -0
- package/dist/db/schema/outbox.d.ts +195 -0
- package/dist/db/schema/outbox.d.ts.map +1 -0
- package/dist/db/schema/outbox.js +5 -0
- package/dist/db/schema/outbox.js.map +1 -0
- package/dist/db/schema/webhook-deliveries.d.ts +76 -0
- package/dist/db/schema/webhook-deliveries.d.ts.map +1 -0
- package/dist/db/schema/webhook-deliveries.js +22 -0
- package/dist/db/schema/webhook-deliveries.js.map +1 -0
- package/dist/db/webhook-deliveries.d.ts +55 -0
- package/dist/db/webhook-deliveries.d.ts.map +1 -0
- package/dist/db/webhook-deliveries.js +132 -0
- package/dist/db/webhook-deliveries.js.map +1 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +3 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instance.d.ts +8 -0
- package/dist/metrics/instance.d.ts.map +1 -0
- package/dist/metrics/instance.js +17 -0
- package/dist/metrics/instance.js.map +1 -0
- package/dist/presentation/dto/integrations.d.ts +36 -0
- package/dist/presentation/dto/integrations.d.ts.map +1 -0
- package/dist/presentation/dto/integrations.js +26 -0
- package/dist/presentation/dto/integrations.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/audit.d.ts +24 -0
- package/dist/presentation/routes/agent-tools-gateway/audit.d.ts.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/audit.js +52 -0
- package/dist/presentation/routes/agent-tools-gateway/audit.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/dispatch.d.ts +7 -0
- package/dist/presentation/routes/agent-tools-gateway/dispatch.d.ts.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/dispatch.js +108 -0
- package/dist/presentation/routes/agent-tools-gateway/dispatch.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/index.d.ts +12 -0
- package/dist/presentation/routes/agent-tools-gateway/index.d.ts.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/index.js +46 -0
- package/dist/presentation/routes/agent-tools-gateway/index.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.d.ts +17 -0
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.d.ts.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.js +126 -0
- package/dist/presentation/routes/agent-tools-gateway/mcp-server.js.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.d.ts +37 -0
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.d.ts.map +1 -0
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.js +145 -0
- package/dist/presentation/routes/agent-tools-gateway/resolve-authorized-tools.js.map +1 -0
- package/dist/presentation/routes/errors.d.ts +2 -0
- package/dist/presentation/routes/errors.d.ts.map +1 -0
- package/dist/presentation/routes/errors.js +53 -0
- package/dist/presentation/routes/errors.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +14 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +26 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/list-connections.d.ts +3 -0
- package/dist/presentation/routes/list-connections.d.ts.map +1 -0
- package/dist/presentation/routes/list-connections.js +58 -0
- package/dist/presentation/routes/list-connections.js.map +1 -0
- package/dist/presentation/routes/list-providers.d.ts +3 -0
- package/dist/presentation/routes/list-providers.d.ts.map +1 -0
- package/dist/presentation/routes/list-providers.js +27 -0
- package/dist/presentation/routes/list-providers.js.map +1 -0
- package/dist/presentation/routes/list-repositories.d.ts +3 -0
- package/dist/presentation/routes/list-repositories.d.ts.map +1 -0
- package/dist/presentation/routes/list-repositories.js +41 -0
- package/dist/presentation/routes/list-repositories.js.map +1 -0
- package/dist/presentation/routes/manage-connections.d.ts +4 -0
- package/dist/presentation/routes/manage-connections.d.ts.map +1 -0
- package/dist/presentation/routes/manage-connections.js +81 -0
- package/dist/presentation/routes/manage-connections.js.map +1 -0
- package/dist/providers/connection-slug.d.ts +2 -0
- package/dist/providers/connection-slug.d.ts.map +1 -0
- package/dist/providers/connection-slug.js +19 -0
- package/dist/providers/connection-slug.js.map +1 -0
- package/dist/providers/cron.d.ts +3 -0
- package/dist/providers/cron.d.ts.map +1 -0
- package/dist/providers/cron.js +13 -0
- package/dist/providers/cron.js.map +1 -0
- package/dist/providers/gitea.d.ts +3 -0
- package/dist/providers/gitea.d.ts.map +1 -0
- package/dist/providers/gitea.js +75 -0
- package/dist/providers/gitea.js.map +1 -0
- package/dist/providers/github.d.ts +3 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +109 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/providers/linear.d.ts +3 -0
- package/dist/providers/linear.d.ts.map +1 -0
- package/dist/providers/linear.js +134 -0
- package/dist/providers/linear.js.map +1 -0
- package/dist/providers/modules.d.ts +3 -0
- package/dist/providers/modules.d.ts.map +1 -0
- package/dist/providers/modules.js +26 -0
- package/dist/providers/modules.js.map +1 -0
- package/dist/providers/sentry.d.ts +3 -0
- package/dist/providers/sentry.d.ts.map +1 -0
- package/dist/providers/sentry.js +83 -0
- package/dist/providers/sentry.js.map +1 -0
- package/dist/providers/types.d.ts +58 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +3 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/providers/webhook.d.ts +3 -0
- package/dist/providers/webhook.d.ts.map +1 -0
- package/dist/providers/webhook.js +24 -0
- package/dist/providers/webhook.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +5 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +8 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/prune-webhook-deliveries.d.ts +4 -0
- package/dist/temporal/activities/prune-webhook-deliveries.d.ts.map +1 -0
- package/dist/temporal/activities/prune-webhook-deliveries.js +11 -0
- package/dist/temporal/activities/prune-webhook-deliveries.js.map +1 -0
- package/dist/temporal/constants.d.ts +3 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +4 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +2 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +3 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/temporal/workflows/prune-webhook-deliveries-cron.d.ts +2 -0
- package/dist/temporal/workflows/prune-webhook-deliveries-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/prune-webhook-deliveries-cron.js +14 -0
- package/dist/temporal/workflows/prune-webhook-deliveries-cron.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +41 -0
- package/drizzle/meta/0001_snapshot.json +341 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +7 -0
- package/package.json +85 -0
- package/src/config.test.ts +32 -0
- package/src/config.ts +28 -0
- package/src/core/agent-tool-selection.test.ts +137 -0
- package/src/core/agent-tool-selection.ts +80 -0
- package/src/core/entities/connection.ts +4 -0
- package/src/core/entities/provider.ts +21 -0
- package/src/core/errors.ts +55 -0
- package/src/core/providers/agent-tools.ts +10 -0
- package/src/core/providers/redact-checkout-spec.test.ts +78 -0
- package/src/core/providers/redact-checkout-spec.ts +20 -0
- package/src/core/providers/registry.test.ts +138 -0
- package/src/core/providers/registry.ts +90 -0
- package/src/core/providers/source-control.ts +17 -0
- package/src/core/source-control-service.test.ts +230 -0
- package/src/core/source-control-service.ts +161 -0
- package/src/db/connections.test.ts +296 -0
- package/src/db/connections.ts +262 -0
- package/src/db/db.ts +22 -0
- package/src/db/migrations.ts +4 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/connections.ts +49 -0
- package/src/db/schema/outbox.ts +4 -0
- package/src/db/schema/webhook-deliveries.ts +19 -0
- package/src/db/webhook-deliveries.test.ts +267 -0
- package/src/db/webhook-deliveries.ts +207 -0
- package/src/index.ts +212 -0
- package/src/metrics/index.ts +1 -0
- package/src/metrics/instance.ts +35 -0
- package/src/presentation/dto/integrations.ts +39 -0
- package/src/presentation/routes/agent-tools-gateway/agent-tools-gateway.route.test.ts +371 -0
- package/src/presentation/routes/agent-tools-gateway/audit.test.ts +86 -0
- package/src/presentation/routes/agent-tools-gateway/audit.ts +90 -0
- package/src/presentation/routes/agent-tools-gateway/dispatch.ts +139 -0
- package/src/presentation/routes/agent-tools-gateway/index.ts +62 -0
- package/src/presentation/routes/agent-tools-gateway/mcp-server.test.ts +308 -0
- package/src/presentation/routes/agent-tools-gateway/mcp-server.ts +155 -0
- package/src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.test.ts +181 -0
- package/src/presentation/routes/agent-tools-gateway/resolve-authorized-tools.ts +245 -0
- package/src/presentation/routes/errors.ts +63 -0
- package/src/presentation/routes/index.ts +53 -0
- package/src/presentation/routes/list-connections.test.ts +227 -0
- package/src/presentation/routes/list-connections.ts +56 -0
- package/src/presentation/routes/list-providers.test.ts +113 -0
- package/src/presentation/routes/list-providers.ts +28 -0
- package/src/presentation/routes/list-repositories.test.ts +150 -0
- package/src/presentation/routes/list-repositories.ts +47 -0
- package/src/presentation/routes/manage-connections.test.ts +125 -0
- package/src/presentation/routes/manage-connections.ts +77 -0
- package/src/providers/connection-slug.ts +19 -0
- package/src/providers/cron.ts +13 -0
- package/src/providers/gitea.ts +103 -0
- package/src/providers/github.ts +150 -0
- package/src/providers/linear.ts +179 -0
- package/src/providers/modules.test.ts +40 -0
- package/src/providers/modules.ts +32 -0
- package/src/providers/sentry.ts +113 -0
- package/src/providers/types.ts +52 -0
- package/src/providers/webhook.ts +30 -0
- package/src/temporal/activities/index.ts +7 -0
- package/src/temporal/activities/prune-webhook-deliveries.test.ts +39 -0
- package/src/temporal/activities/prune-webhook-deliveries.ts +9 -0
- package/src/temporal/constants.ts +3 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/src/temporal/workflows/prune-webhook-deliveries-cron.ts +15 -0
- package/test/agent-tools-gateway-helpers.ts +210 -0
- package/test/env.ts +23 -0
- package/test/factories/connection.ts +21 -0
- package/test/globalSetup.ts +22 -0
- package/test/index.ts +1 -0
- package/test/route-utils.ts +104 -0
- package/test/setup.ts +19 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IntegrationCapability, IntegrationProvider, IntegrationProviderAdapters, IntegrationProviderKind, RegisteredIntegrationProvider } from '#core/entities/provider.js';
|
|
2
|
+
export interface IntegrationProviderRegistry {
|
|
3
|
+
list(capability?: IntegrationCapability | undefined): RegisteredIntegrationProvider[];
|
|
4
|
+
get(provider: IntegrationProviderKind): RegisteredIntegrationProvider;
|
|
5
|
+
getAdapter<Capability extends IntegrationCapability>(provider: IntegrationProviderKind, capability: Capability): NonNullable<IntegrationProviderAdapters[Capability]>;
|
|
6
|
+
getSourceControl(provider: IntegrationProviderKind): NonNullable<IntegrationProviderAdapters['source_control']>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createIntegrationProviderRegistry(providers: IntegrationProvider[]): IntegrationProviderRegistry;
|
|
9
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/providers/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC9B,MAAM,4BAA4B,CAAC;AAMpC,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,UAAU,CAAC,EAAE,qBAAqB,GAAG,SAAS,GAAG,6BAA6B,EAAE,CAAC;IACtF,GAAG,CAAC,QAAQ,EAAE,uBAAuB,GAAG,6BAA6B,CAAC;IACtE,UAAU,CAAC,UAAU,SAAS,qBAAqB,EACjD,QAAQ,EAAE,uBAAuB,EACjC,UAAU,EAAE,UAAU,GACrB,WAAW,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD,gBAAgB,CACd,QAAQ,EAAE,uBAAuB,GAChC,WAAW,CAAC,2BAA2B,CAAC,gBAAgB,CAAC,CAAC,CAAC;CAC/D;AAED,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,mBAAmB,EAAE,GAC/B,2BAA2B,CAE7B"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isLowercaseAlphaSlug } from '@shipfox/regex';
|
|
2
|
+
import { IntegrationCapabilityUnavailableError, IntegrationProviderUnavailableError } from '#core/errors.js';
|
|
3
|
+
export function createIntegrationProviderRegistry(providers) {
|
|
4
|
+
return new MapIntegrationProviderRegistry(providers);
|
|
5
|
+
}
|
|
6
|
+
let MapIntegrationProviderRegistry = class MapIntegrationProviderRegistry {
|
|
7
|
+
constructor(providers){
|
|
8
|
+
this.providers = new Map();
|
|
9
|
+
for (const provider of providers){
|
|
10
|
+
if (!isLowercaseAlphaSlug(provider.provider)) {
|
|
11
|
+
throw new Error(`Invalid integration provider id: ${provider.provider}`);
|
|
12
|
+
}
|
|
13
|
+
if (this.providers.has(provider.provider)) {
|
|
14
|
+
throw new Error(`Duplicate integration provider registered: ${provider.provider}`);
|
|
15
|
+
}
|
|
16
|
+
this.providers.set(provider.provider, normalizeProvider(provider));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
list(capability) {
|
|
20
|
+
const providers = [
|
|
21
|
+
...this.providers.values()
|
|
22
|
+
];
|
|
23
|
+
if (!capability) return providers;
|
|
24
|
+
return providers.filter((provider)=>provider.capabilities.includes(capability));
|
|
25
|
+
}
|
|
26
|
+
get(provider) {
|
|
27
|
+
const resolved = this.providers.get(provider);
|
|
28
|
+
if (!resolved) throw new IntegrationProviderUnavailableError(provider);
|
|
29
|
+
return resolved;
|
|
30
|
+
}
|
|
31
|
+
getAdapter(provider, capability) {
|
|
32
|
+
const resolved = this.get(provider);
|
|
33
|
+
const adapter = resolved.adapters[capability];
|
|
34
|
+
if (!adapter) {
|
|
35
|
+
throw new IntegrationCapabilityUnavailableError(capability, provider);
|
|
36
|
+
}
|
|
37
|
+
return adapter;
|
|
38
|
+
}
|
|
39
|
+
getSourceControl(provider) {
|
|
40
|
+
return this.getAdapter(provider, 'source_control');
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function normalizeProvider(provider) {
|
|
44
|
+
const adapters = provider.adapters ?? {};
|
|
45
|
+
return {
|
|
46
|
+
...provider,
|
|
47
|
+
adapters,
|
|
48
|
+
capabilities: Object.entries(adapters).filter(([, adapter])=>Boolean(adapter)).map(([capability])=>capability)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/providers/registry.ts"],"sourcesContent":["import {isLowercaseAlphaSlug} from '@shipfox/regex';\nimport type {\n IntegrationCapability,\n IntegrationProvider,\n IntegrationProviderAdapters,\n IntegrationProviderKind,\n RegisteredIntegrationProvider,\n} from '#core/entities/provider.js';\nimport {\n IntegrationCapabilityUnavailableError,\n IntegrationProviderUnavailableError,\n} from '#core/errors.js';\n\nexport interface IntegrationProviderRegistry {\n list(capability?: IntegrationCapability | undefined): RegisteredIntegrationProvider[];\n get(provider: IntegrationProviderKind): RegisteredIntegrationProvider;\n getAdapter<Capability extends IntegrationCapability>(\n provider: IntegrationProviderKind,\n capability: Capability,\n ): NonNullable<IntegrationProviderAdapters[Capability]>;\n getSourceControl(\n provider: IntegrationProviderKind,\n ): NonNullable<IntegrationProviderAdapters['source_control']>;\n}\n\nexport function createIntegrationProviderRegistry(\n providers: IntegrationProvider[],\n): IntegrationProviderRegistry {\n return new MapIntegrationProviderRegistry(providers);\n}\n\nclass MapIntegrationProviderRegistry implements IntegrationProviderRegistry {\n private readonly providers: Map<IntegrationProviderKind, RegisteredIntegrationProvider>;\n\n constructor(providers: IntegrationProvider[]) {\n this.providers = new Map();\n\n for (const provider of providers) {\n if (!isLowercaseAlphaSlug(provider.provider)) {\n throw new Error(`Invalid integration provider id: ${provider.provider}`);\n }\n if (this.providers.has(provider.provider)) {\n throw new Error(`Duplicate integration provider registered: ${provider.provider}`);\n }\n\n this.providers.set(provider.provider, normalizeProvider(provider));\n }\n }\n\n list(capability?: IntegrationCapability | undefined): RegisteredIntegrationProvider[] {\n const providers = [...this.providers.values()];\n if (!capability) return providers;\n return providers.filter((provider) => provider.capabilities.includes(capability));\n }\n\n get(provider: IntegrationProviderKind): RegisteredIntegrationProvider {\n const resolved = this.providers.get(provider);\n if (!resolved) throw new IntegrationProviderUnavailableError(provider);\n return resolved;\n }\n\n getAdapter<Capability extends IntegrationCapability>(\n provider: IntegrationProviderKind,\n capability: Capability,\n ): NonNullable<IntegrationProviderAdapters[Capability]> {\n const resolved = this.get(provider);\n const adapter = resolved.adapters[capability];\n if (!adapter) {\n throw new IntegrationCapabilityUnavailableError(capability, provider);\n }\n return adapter as NonNullable<IntegrationProviderAdapters[Capability]>;\n }\n\n getSourceControl(\n provider: IntegrationProviderKind,\n ): NonNullable<IntegrationProviderAdapters['source_control']> {\n return this.getAdapter(provider, 'source_control');\n }\n}\n\nfunction normalizeProvider(provider: IntegrationProvider): RegisteredIntegrationProvider {\n const adapters = provider.adapters ?? {};\n return {\n ...provider,\n adapters,\n capabilities: Object.entries(adapters)\n .filter(([, adapter]) => Boolean(adapter))\n .map(([capability]) => capability as IntegrationCapability),\n };\n}\n"],"names":["isLowercaseAlphaSlug","IntegrationCapabilityUnavailableError","IntegrationProviderUnavailableError","createIntegrationProviderRegistry","providers","MapIntegrationProviderRegistry","Map","provider","Error","has","set","normalizeProvider","list","capability","values","filter","capabilities","includes","get","resolved","getAdapter","adapter","adapters","getSourceControl","Object","entries","Boolean","map"],"mappings":"AAAA,SAAQA,oBAAoB,QAAO,iBAAiB;AAQpD,SACEC,qCAAqC,EACrCC,mCAAmC,QAC9B,kBAAkB;AAczB,OAAO,SAASC,kCACdC,SAAgC;IAEhC,OAAO,IAAIC,+BAA+BD;AAC5C;AAEA,IAAA,AAAMC,iCAAN,MAAMA;IAGJ,YAAYD,SAAgC,CAAE;QAC5C,IAAI,CAACA,SAAS,GAAG,IAAIE;QAErB,KAAK,MAAMC,YAAYH,UAAW;YAChC,IAAI,CAACJ,qBAAqBO,SAASA,QAAQ,GAAG;gBAC5C,MAAM,IAAIC,MAAM,CAAC,iCAAiC,EAAED,SAASA,QAAQ,EAAE;YACzE;YACA,IAAI,IAAI,CAACH,SAAS,CAACK,GAAG,CAACF,SAASA,QAAQ,GAAG;gBACzC,MAAM,IAAIC,MAAM,CAAC,2CAA2C,EAAED,SAASA,QAAQ,EAAE;YACnF;YAEA,IAAI,CAACH,SAAS,CAACM,GAAG,CAACH,SAASA,QAAQ,EAAEI,kBAAkBJ;QAC1D;IACF;IAEAK,KAAKC,UAA8C,EAAmC;QACpF,MAAMT,YAAY;eAAI,IAAI,CAACA,SAAS,CAACU,MAAM;SAAG;QAC9C,IAAI,CAACD,YAAY,OAAOT;QACxB,OAAOA,UAAUW,MAAM,CAAC,CAACR,WAAaA,SAASS,YAAY,CAACC,QAAQ,CAACJ;IACvE;IAEAK,IAAIX,QAAiC,EAAiC;QACpE,MAAMY,WAAW,IAAI,CAACf,SAAS,CAACc,GAAG,CAACX;QACpC,IAAI,CAACY,UAAU,MAAM,IAAIjB,oCAAoCK;QAC7D,OAAOY;IACT;IAEAC,WACEb,QAAiC,EACjCM,UAAsB,EACgC;QACtD,MAAMM,WAAW,IAAI,CAACD,GAAG,CAACX;QAC1B,MAAMc,UAAUF,SAASG,QAAQ,CAACT,WAAW;QAC7C,IAAI,CAACQ,SAAS;YACZ,MAAM,IAAIpB,sCAAsCY,YAAYN;QAC9D;QACA,OAAOc;IACT;IAEAE,iBACEhB,QAAiC,EAC2B;QAC5D,OAAO,IAAI,CAACa,UAAU,CAACb,UAAU;IACnC;AACF;AAEA,SAASI,kBAAkBJ,QAA6B;IACtD,MAAMe,WAAWf,SAASe,QAAQ,IAAI,CAAC;IACvC,OAAO;QACL,GAAGf,QAAQ;QACXe;QACAN,cAAcQ,OAAOC,OAAO,CAACH,UAC1BP,MAAM,CAAC,CAAC,GAAGM,QAAQ,GAAKK,QAAQL,UAChCM,GAAG,CAAC,CAAC,CAACd,WAAW,GAAKA;IAC3B;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { CheckoutCredentials, CheckoutPermissions, CheckoutSpec, CreateCheckoutSpecInput, FetchFileInput, FileEntry, FilePage, FileSnapshot, ListFilesInput, ListRepositoriesInput, RepositoryPage, RepositorySnapshot, RepositoryVisibility, ResolveRepositoryInput, SourceControlProvider, } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
//# sourceMappingURL=source-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-control.d.ts","sourceRoot":"","sources":["../../../src/core/providers/source-control.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,uBAAuB,EACvB,cAAc,EACd,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/providers/source-control.ts"],"sourcesContent":["export type {\n CheckoutCredentials,\n CheckoutPermissions,\n CheckoutSpec,\n CreateCheckoutSpecInput,\n FetchFileInput,\n FileEntry,\n FilePage,\n FileSnapshot,\n ListFilesInput,\n ListRepositoriesInput,\n RepositoryPage,\n RepositorySnapshot,\n RepositoryVisibility,\n ResolveRepositoryInput,\n SourceControlProvider,\n} from '@shipfox/api-integration-core-dto';\n"],"names":[],"mappings":"AAAA,WAgB2C"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { IntegrationConnection } from './entities/connection.js';
|
|
2
|
+
import type { IntegrationProviderRegistry } from './providers/registry.js';
|
|
3
|
+
import type { CheckoutPermissions, CheckoutSpec, FilePage, FileSnapshot, RepositoryPage, RepositorySnapshot } from './providers/source-control.js';
|
|
4
|
+
export interface IntegrationSourceControlService {
|
|
5
|
+
getConnection(connectionId: string): Promise<IntegrationConnection>;
|
|
6
|
+
listRepositories(input: ListSourceRepositoriesInput): Promise<RepositoryPage>;
|
|
7
|
+
resolveRepository(input: ResolveSourceRepositoryInput): Promise<ResolvedSourceRepository>;
|
|
8
|
+
listFiles(input: ListSourceFilesInput): Promise<FilePage>;
|
|
9
|
+
fetchFile(input: FetchSourceFileInput): Promise<FileSnapshot>;
|
|
10
|
+
createCheckoutSpec(input: CreateSourceCheckoutSpecInput): Promise<CheckoutSpec>;
|
|
11
|
+
}
|
|
12
|
+
export interface ListSourceRepositoriesInput {
|
|
13
|
+
connection: IntegrationConnection;
|
|
14
|
+
limit: number;
|
|
15
|
+
cursor?: string | undefined;
|
|
16
|
+
search?: string | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface ResolveSourceRepositoryInput {
|
|
19
|
+
workspaceId: string;
|
|
20
|
+
connectionId: string;
|
|
21
|
+
externalRepositoryId: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ListSourceFilesInput extends ResolveSourceRepositoryInput {
|
|
24
|
+
ref: string;
|
|
25
|
+
prefix: string;
|
|
26
|
+
limit: number;
|
|
27
|
+
cursor?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
export interface FetchSourceFileInput extends ResolveSourceRepositoryInput {
|
|
30
|
+
ref: string;
|
|
31
|
+
path: string;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateSourceCheckoutSpecInput extends ResolveSourceRepositoryInput {
|
|
34
|
+
ref?: string | undefined;
|
|
35
|
+
permissions?: CheckoutPermissions | undefined;
|
|
36
|
+
}
|
|
37
|
+
export interface ResolvedSourceRepository {
|
|
38
|
+
connection: IntegrationConnection;
|
|
39
|
+
repository: RepositorySnapshot;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateIntegrationSourceControlServiceOptions {
|
|
42
|
+
registry: IntegrationProviderRegistry;
|
|
43
|
+
getIntegrationConnectionById: (connectionId: string) => Promise<IntegrationConnection | undefined>;
|
|
44
|
+
}
|
|
45
|
+
export declare function createSourceControlIntegrationService({ registry, getIntegrationConnectionById, }: CreateIntegrationSourceControlServiceOptions): IntegrationSourceControlService;
|
|
46
|
+
//# sourceMappingURL=source-control-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-control-service.d.ts","sourceRoot":"","sources":["../../src/core/source-control-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,0BAA0B,CAAC;AAOpE,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,+BAA+B;IAC9C,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACpE,gBAAgB,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9E,iBAAiB,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC1F,SAAS,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,SAAS,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9D,kBAAkB,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAqB,SAAQ,4BAA4B;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAqB,SAAQ,4BAA4B;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,6BAA8B,SAAQ,4BAA4B;IACjF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,qBAAqB,CAAC;IAClC,UAAU,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,4CAA4C;IAC3D,QAAQ,EAAE,2BAA2B,CAAC;IACtC,4BAA4B,EAAE,CAC5B,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAAC;CACjD;AAED,wBAAgB,qCAAqC,CAAC,EACpD,QAAQ,EACR,4BAA4B,GAC7B,EAAE,4CAA4C,GAAG,+BAA+B,CAyFhF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { IntegrationCheckoutUnsupportedError, IntegrationConnectionInactiveError, IntegrationConnectionNotFoundError, IntegrationConnectionWorkspaceMismatchError } from './errors.js';
|
|
2
|
+
export function createSourceControlIntegrationService({ registry, getIntegrationConnectionById }) {
|
|
3
|
+
async function getConnection(connectionId) {
|
|
4
|
+
const connection = await getIntegrationConnectionById(connectionId);
|
|
5
|
+
if (!connection) throw new IntegrationConnectionNotFoundError(connectionId);
|
|
6
|
+
if (connection.lifecycleStatus !== 'active') {
|
|
7
|
+
throw new IntegrationConnectionInactiveError(connection.id);
|
|
8
|
+
}
|
|
9
|
+
return connection;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
getConnection,
|
|
13
|
+
async listRepositories ({ connection, limit, cursor, search }) {
|
|
14
|
+
const sourceControl = registry.getAdapter(connection.provider, 'source_control');
|
|
15
|
+
return await sourceControl.listRepositories({
|
|
16
|
+
connection,
|
|
17
|
+
limit,
|
|
18
|
+
cursor,
|
|
19
|
+
search
|
|
20
|
+
});
|
|
21
|
+
},
|
|
22
|
+
async resolveRepository ({ workspaceId, connectionId, externalRepositoryId }) {
|
|
23
|
+
const connection = await getConnection(connectionId);
|
|
24
|
+
if (connection.workspaceId !== workspaceId) {
|
|
25
|
+
throw new IntegrationConnectionWorkspaceMismatchError(connectionId);
|
|
26
|
+
}
|
|
27
|
+
const sourceControl = registry.getAdapter(connection.provider, 'source_control');
|
|
28
|
+
const repository = await sourceControl.resolveRepository({
|
|
29
|
+
connection,
|
|
30
|
+
externalRepositoryId
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
connection,
|
|
34
|
+
repository
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
async listFiles ({ workspaceId, connectionId, externalRepositoryId, ref, prefix, limit, cursor }) {
|
|
38
|
+
const connection = await getConnection(connectionId);
|
|
39
|
+
if (connection.workspaceId !== workspaceId) {
|
|
40
|
+
throw new IntegrationConnectionWorkspaceMismatchError(connectionId);
|
|
41
|
+
}
|
|
42
|
+
const sourceControl = registry.getAdapter(connection.provider, 'source_control');
|
|
43
|
+
return await sourceControl.listFiles({
|
|
44
|
+
connection,
|
|
45
|
+
externalRepositoryId,
|
|
46
|
+
ref,
|
|
47
|
+
prefix,
|
|
48
|
+
limit,
|
|
49
|
+
cursor
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
async fetchFile ({ workspaceId, connectionId, externalRepositoryId, ref, path }) {
|
|
53
|
+
const connection = await getConnection(connectionId);
|
|
54
|
+
if (connection.workspaceId !== workspaceId) {
|
|
55
|
+
throw new IntegrationConnectionWorkspaceMismatchError(connectionId);
|
|
56
|
+
}
|
|
57
|
+
const sourceControl = registry.getAdapter(connection.provider, 'source_control');
|
|
58
|
+
return await sourceControl.fetchFile({
|
|
59
|
+
connection,
|
|
60
|
+
externalRepositoryId,
|
|
61
|
+
ref,
|
|
62
|
+
path
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
async createCheckoutSpec ({ workspaceId, connectionId, externalRepositoryId, ref, permissions }) {
|
|
66
|
+
const connection = await getConnection(connectionId);
|
|
67
|
+
if (connection.workspaceId !== workspaceId) {
|
|
68
|
+
throw new IntegrationConnectionWorkspaceMismatchError(connectionId);
|
|
69
|
+
}
|
|
70
|
+
const sourceControl = registry.getAdapter(connection.provider, 'source_control');
|
|
71
|
+
if (!sourceControl.createCheckoutSpec) {
|
|
72
|
+
throw new IntegrationCheckoutUnsupportedError(connection.provider);
|
|
73
|
+
}
|
|
74
|
+
return await sourceControl.createCheckoutSpec({
|
|
75
|
+
connection,
|
|
76
|
+
externalRepositoryId,
|
|
77
|
+
ref,
|
|
78
|
+
permissions
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=source-control-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/source-control-service.ts"],"sourcesContent":["import type {IntegrationConnection} from './entities/connection.js';\nimport {\n IntegrationCheckoutUnsupportedError,\n IntegrationConnectionInactiveError,\n IntegrationConnectionNotFoundError,\n IntegrationConnectionWorkspaceMismatchError,\n} from './errors.js';\nimport type {IntegrationProviderRegistry} from './providers/registry.js';\nimport type {\n CheckoutPermissions,\n CheckoutSpec,\n FilePage,\n FileSnapshot,\n RepositoryPage,\n RepositorySnapshot,\n} from './providers/source-control.js';\n\nexport interface IntegrationSourceControlService {\n getConnection(connectionId: string): Promise<IntegrationConnection>;\n listRepositories(input: ListSourceRepositoriesInput): Promise<RepositoryPage>;\n resolveRepository(input: ResolveSourceRepositoryInput): Promise<ResolvedSourceRepository>;\n listFiles(input: ListSourceFilesInput): Promise<FilePage>;\n fetchFile(input: FetchSourceFileInput): Promise<FileSnapshot>;\n createCheckoutSpec(input: CreateSourceCheckoutSpecInput): Promise<CheckoutSpec>;\n}\n\nexport interface ListSourceRepositoriesInput {\n connection: IntegrationConnection;\n limit: number;\n cursor?: string | undefined;\n search?: string | undefined;\n}\n\nexport interface ResolveSourceRepositoryInput {\n workspaceId: string;\n connectionId: string;\n externalRepositoryId: string;\n}\n\nexport interface ListSourceFilesInput extends ResolveSourceRepositoryInput {\n ref: string;\n prefix: string;\n limit: number;\n cursor?: string | undefined;\n}\n\nexport interface FetchSourceFileInput extends ResolveSourceRepositoryInput {\n ref: string;\n path: string;\n}\n\nexport interface CreateSourceCheckoutSpecInput extends ResolveSourceRepositoryInput {\n ref?: string | undefined;\n permissions?: CheckoutPermissions | undefined;\n}\n\nexport interface ResolvedSourceRepository {\n connection: IntegrationConnection;\n repository: RepositorySnapshot;\n}\n\nexport interface CreateIntegrationSourceControlServiceOptions {\n registry: IntegrationProviderRegistry;\n getIntegrationConnectionById: (\n connectionId: string,\n ) => Promise<IntegrationConnection | undefined>;\n}\n\nexport function createSourceControlIntegrationService({\n registry,\n getIntegrationConnectionById,\n}: CreateIntegrationSourceControlServiceOptions): IntegrationSourceControlService {\n async function getConnection(connectionId: string): Promise<IntegrationConnection> {\n const connection = await getIntegrationConnectionById(connectionId);\n if (!connection) throw new IntegrationConnectionNotFoundError(connectionId);\n if (connection.lifecycleStatus !== 'active') {\n throw new IntegrationConnectionInactiveError(connection.id);\n }\n\n return connection;\n }\n\n return {\n getConnection,\n\n async listRepositories({connection, limit, cursor, search}) {\n const sourceControl = registry.getAdapter(connection.provider, 'source_control');\n return await sourceControl.listRepositories({\n connection,\n limit,\n cursor,\n search,\n });\n },\n\n async resolveRepository({workspaceId, connectionId, externalRepositoryId}) {\n const connection = await getConnection(connectionId);\n if (connection.workspaceId !== workspaceId) {\n throw new IntegrationConnectionWorkspaceMismatchError(connectionId);\n }\n const sourceControl = registry.getAdapter(connection.provider, 'source_control');\n\n const repository = await sourceControl.resolveRepository({\n connection,\n externalRepositoryId,\n });\n\n return {connection, repository};\n },\n\n async listFiles({workspaceId, connectionId, externalRepositoryId, ref, prefix, limit, cursor}) {\n const connection = await getConnection(connectionId);\n if (connection.workspaceId !== workspaceId) {\n throw new IntegrationConnectionWorkspaceMismatchError(connectionId);\n }\n const sourceControl = registry.getAdapter(connection.provider, 'source_control');\n\n return await sourceControl.listFiles({\n connection,\n externalRepositoryId,\n ref,\n prefix,\n limit,\n cursor,\n });\n },\n\n async fetchFile({workspaceId, connectionId, externalRepositoryId, ref, path}) {\n const connection = await getConnection(connectionId);\n if (connection.workspaceId !== workspaceId) {\n throw new IntegrationConnectionWorkspaceMismatchError(connectionId);\n }\n const sourceControl = registry.getAdapter(connection.provider, 'source_control');\n\n return await sourceControl.fetchFile({\n connection,\n externalRepositoryId,\n ref,\n path,\n });\n },\n\n async createCheckoutSpec({workspaceId, connectionId, externalRepositoryId, ref, permissions}) {\n const connection = await getConnection(connectionId);\n if (connection.workspaceId !== workspaceId) {\n throw new IntegrationConnectionWorkspaceMismatchError(connectionId);\n }\n const sourceControl = registry.getAdapter(connection.provider, 'source_control');\n if (!sourceControl.createCheckoutSpec) {\n throw new IntegrationCheckoutUnsupportedError(connection.provider);\n }\n\n return await sourceControl.createCheckoutSpec({\n connection,\n externalRepositoryId,\n ref,\n permissions,\n });\n },\n };\n}\n"],"names":["IntegrationCheckoutUnsupportedError","IntegrationConnectionInactiveError","IntegrationConnectionNotFoundError","IntegrationConnectionWorkspaceMismatchError","createSourceControlIntegrationService","registry","getIntegrationConnectionById","getConnection","connectionId","connection","lifecycleStatus","id","listRepositories","limit","cursor","search","sourceControl","getAdapter","provider","resolveRepository","workspaceId","externalRepositoryId","repository","listFiles","ref","prefix","fetchFile","path","createCheckoutSpec","permissions"],"mappings":"AACA,SACEA,mCAAmC,EACnCC,kCAAkC,EAClCC,kCAAkC,EAClCC,2CAA2C,QACtC,cAAc;AA8DrB,OAAO,SAASC,sCAAsC,EACpDC,QAAQ,EACRC,4BAA4B,EACiB;IAC7C,eAAeC,cAAcC,YAAoB;QAC/C,MAAMC,aAAa,MAAMH,6BAA6BE;QACtD,IAAI,CAACC,YAAY,MAAM,IAAIP,mCAAmCM;QAC9D,IAAIC,WAAWC,eAAe,KAAK,UAAU;YAC3C,MAAM,IAAIT,mCAAmCQ,WAAWE,EAAE;QAC5D;QAEA,OAAOF;IACT;IAEA,OAAO;QACLF;QAEA,MAAMK,kBAAiB,EAACH,UAAU,EAAEI,KAAK,EAAEC,MAAM,EAAEC,MAAM,EAAC;YACxD,MAAMC,gBAAgBX,SAASY,UAAU,CAACR,WAAWS,QAAQ,EAAE;YAC/D,OAAO,MAAMF,cAAcJ,gBAAgB,CAAC;gBAC1CH;gBACAI;gBACAC;gBACAC;YACF;QACF;QAEA,MAAMI,mBAAkB,EAACC,WAAW,EAAEZ,YAAY,EAAEa,oBAAoB,EAAC;YACvE,MAAMZ,aAAa,MAAMF,cAAcC;YACvC,IAAIC,WAAWW,WAAW,KAAKA,aAAa;gBAC1C,MAAM,IAAIjB,4CAA4CK;YACxD;YACA,MAAMQ,gBAAgBX,SAASY,UAAU,CAACR,WAAWS,QAAQ,EAAE;YAE/D,MAAMI,aAAa,MAAMN,cAAcG,iBAAiB,CAAC;gBACvDV;gBACAY;YACF;YAEA,OAAO;gBAACZ;gBAAYa;YAAU;QAChC;QAEA,MAAMC,WAAU,EAACH,WAAW,EAAEZ,YAAY,EAAEa,oBAAoB,EAAEG,GAAG,EAAEC,MAAM,EAAEZ,KAAK,EAAEC,MAAM,EAAC;YAC3F,MAAML,aAAa,MAAMF,cAAcC;YACvC,IAAIC,WAAWW,WAAW,KAAKA,aAAa;gBAC1C,MAAM,IAAIjB,4CAA4CK;YACxD;YACA,MAAMQ,gBAAgBX,SAASY,UAAU,CAACR,WAAWS,QAAQ,EAAE;YAE/D,OAAO,MAAMF,cAAcO,SAAS,CAAC;gBACnCd;gBACAY;gBACAG;gBACAC;gBACAZ;gBACAC;YACF;QACF;QAEA,MAAMY,WAAU,EAACN,WAAW,EAAEZ,YAAY,EAAEa,oBAAoB,EAAEG,GAAG,EAAEG,IAAI,EAAC;YAC1E,MAAMlB,aAAa,MAAMF,cAAcC;YACvC,IAAIC,WAAWW,WAAW,KAAKA,aAAa;gBAC1C,MAAM,IAAIjB,4CAA4CK;YACxD;YACA,MAAMQ,gBAAgBX,SAASY,UAAU,CAACR,WAAWS,QAAQ,EAAE;YAE/D,OAAO,MAAMF,cAAcU,SAAS,CAAC;gBACnCjB;gBACAY;gBACAG;gBACAG;YACF;QACF;QAEA,MAAMC,oBAAmB,EAACR,WAAW,EAAEZ,YAAY,EAAEa,oBAAoB,EAAEG,GAAG,EAAEK,WAAW,EAAC;YAC1F,MAAMpB,aAAa,MAAMF,cAAcC;YACvC,IAAIC,WAAWW,WAAW,KAAKA,aAAa;gBAC1C,MAAM,IAAIjB,4CAA4CK;YACxD;YACA,MAAMQ,gBAAgBX,SAASY,UAAU,CAACR,WAAWS,QAAQ,EAAE;YAC/D,IAAI,CAACF,cAAcY,kBAAkB,EAAE;gBACrC,MAAM,IAAI5B,oCAAoCS,WAAWS,QAAQ;YACnE;YAEA,OAAO,MAAMF,cAAcY,kBAAkB,CAAC;gBAC5CnB;gBACAY;gBACAG;gBACAK;YACF;QACF;IACF;AACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { IntegrationConnection, IntegrationConnectionLifecycleStatus } from '#core/entities/connection.js';
|
|
2
|
+
import type { IntegrationProviderKind } from '#core/entities/provider.js';
|
|
3
|
+
import { db } from './db.js';
|
|
4
|
+
type IntegrationDb = ReturnType<typeof db>;
|
|
5
|
+
type IntegrationTx = Parameters<Parameters<IntegrationDb['transaction']>[0]>[0];
|
|
6
|
+
export interface UpsertIntegrationConnectionParams {
|
|
7
|
+
workspaceId: string;
|
|
8
|
+
provider: IntegrationProviderKind;
|
|
9
|
+
externalAccountId: string;
|
|
10
|
+
slug: string;
|
|
11
|
+
displayName: string;
|
|
12
|
+
lifecycleStatus?: IntegrationConnectionLifecycleStatus | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function upsertIntegrationConnection(params: UpsertIntegrationConnectionParams, options?: {
|
|
15
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
16
|
+
}): Promise<IntegrationConnection>;
|
|
17
|
+
export interface CreateIntegrationConnectionParams {
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
provider: IntegrationProviderKind;
|
|
20
|
+
externalAccountId: string;
|
|
21
|
+
slug: string;
|
|
22
|
+
displayName: string;
|
|
23
|
+
lifecycleStatus?: IntegrationConnectionLifecycleStatus | undefined;
|
|
24
|
+
}
|
|
25
|
+
export declare function isIntegrationConnectionUniqueViolation(error: unknown): boolean;
|
|
26
|
+
export declare function isIntegrationConnectionSlugUniqueViolation(error: unknown): boolean;
|
|
27
|
+
export declare function createIntegrationConnection(params: CreateIntegrationConnectionParams, options?: {
|
|
28
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
29
|
+
}): Promise<IntegrationConnection>;
|
|
30
|
+
export interface ResolveUniqueConnectionSlugParams {
|
|
31
|
+
workspaceId: string;
|
|
32
|
+
provider: IntegrationProviderKind;
|
|
33
|
+
externalAccountId: string;
|
|
34
|
+
baseSlug: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function resolveUniqueConnectionSlug(params: ResolveUniqueConnectionSlugParams, options?: {
|
|
37
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
38
|
+
}): Promise<string>;
|
|
39
|
+
export type CreateIntegrationConnectionFn = typeof createIntegrationConnection;
|
|
40
|
+
export declare function getIntegrationConnectionById(id: string, options?: {
|
|
41
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
42
|
+
}): Promise<IntegrationConnection | undefined>;
|
|
43
|
+
export type GetIntegrationConnectionByIdFn = typeof getIntegrationConnectionById;
|
|
44
|
+
export interface UpdateIntegrationConnectionLifecycleStatusParams {
|
|
45
|
+
id: string;
|
|
46
|
+
lifecycleStatus: IntegrationConnectionLifecycleStatus;
|
|
47
|
+
}
|
|
48
|
+
export declare function updateIntegrationConnectionLifecycleStatus(params: UpdateIntegrationConnectionLifecycleStatusParams, options?: {
|
|
49
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
50
|
+
}): Promise<IntegrationConnection | undefined>;
|
|
51
|
+
export type UpdateIntegrationConnectionLifecycleStatusFn = typeof updateIntegrationConnectionLifecycleStatus;
|
|
52
|
+
export declare function deleteIntegrationConnection(params: {
|
|
53
|
+
id: string;
|
|
54
|
+
}, options?: {
|
|
55
|
+
tx?: IntegrationDb | IntegrationTx | undefined;
|
|
56
|
+
}): Promise<boolean>;
|
|
57
|
+
export type DeleteIntegrationConnectionFn = typeof deleteIntegrationConnection;
|
|
58
|
+
export interface ListIntegrationConnectionsParams {
|
|
59
|
+
workspaceId: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function listIntegrationConnections(params: ListIntegrationConnectionsParams): Promise<IntegrationConnection[]>;
|
|
62
|
+
export interface ListIntegrationConnectionsByProviderParams {
|
|
63
|
+
provider: IntegrationProviderKind;
|
|
64
|
+
}
|
|
65
|
+
export declare function listIntegrationConnectionsByProvider(params: ListIntegrationConnectionsByProviderParams): Promise<IntegrationConnection[]>;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=connections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/db/connections.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { CONNECTION_SLUG_MAX_LENGTH, ConnectionSlugConflictError } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { and, eq } from 'drizzle-orm';
|
|
3
|
+
import { IntegrationConnectionAlreadyExistsError } from '#core/errors.js';
|
|
4
|
+
import { db } from './db.js';
|
|
5
|
+
import { integrationConnections, toIntegrationConnection } from './schema/connections.js';
|
|
6
|
+
export async function upsertIntegrationConnection(params, options = {}) {
|
|
7
|
+
const executor = options.tx ?? db();
|
|
8
|
+
const now = new Date();
|
|
9
|
+
const [row] = await executor.insert(integrationConnections).values({
|
|
10
|
+
workspaceId: params.workspaceId,
|
|
11
|
+
provider: params.provider,
|
|
12
|
+
externalAccountId: params.externalAccountId,
|
|
13
|
+
slug: params.slug,
|
|
14
|
+
displayName: params.displayName,
|
|
15
|
+
lifecycleStatus: params.lifecycleStatus ?? 'active'
|
|
16
|
+
}).onConflictDoUpdate({
|
|
17
|
+
target: [
|
|
18
|
+
integrationConnections.workspaceId,
|
|
19
|
+
integrationConnections.provider,
|
|
20
|
+
integrationConnections.externalAccountId
|
|
21
|
+
],
|
|
22
|
+
set: {
|
|
23
|
+
displayName: params.displayName,
|
|
24
|
+
lifecycleStatus: params.lifecycleStatus ?? 'active',
|
|
25
|
+
updatedAt: now
|
|
26
|
+
}
|
|
27
|
+
}).returning();
|
|
28
|
+
if (!row) throw new Error('Integration connection upsert returned no rows');
|
|
29
|
+
return toIntegrationConnection(row);
|
|
30
|
+
}
|
|
31
|
+
const INTEGRATION_CONNECTION_EXTERNAL_UNIQUE_CONSTRAINT = 'integrations_connections_workspace_external_unique';
|
|
32
|
+
const INTEGRATION_CONNECTION_SLUG_UNIQUE_CONSTRAINT = 'integrations_connections_workspace_slug_unique';
|
|
33
|
+
export function isIntegrationConnectionUniqueViolation(error) {
|
|
34
|
+
let current = error;
|
|
35
|
+
for(let depth = 0; depth < 5 && current != null; depth += 1){
|
|
36
|
+
if (typeof current !== 'object') return false;
|
|
37
|
+
const { code, constraint } = current;
|
|
38
|
+
if (code === '23505' && constraint === INTEGRATION_CONNECTION_EXTERNAL_UNIQUE_CONSTRAINT) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
current = current.cause;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
export function isIntegrationConnectionSlugUniqueViolation(error) {
|
|
46
|
+
let current = error;
|
|
47
|
+
for(let depth = 0; depth < 5 && current != null; depth += 1){
|
|
48
|
+
if (typeof current !== 'object') return false;
|
|
49
|
+
const { code, constraint } = current;
|
|
50
|
+
if (code === '23505' && constraint === INTEGRATION_CONNECTION_SLUG_UNIQUE_CONSTRAINT) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
current = current.cause;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
export async function createIntegrationConnection(params, options = {}) {
|
|
58
|
+
const executor = options.tx ?? db();
|
|
59
|
+
let rows;
|
|
60
|
+
try {
|
|
61
|
+
rows = await executor.insert(integrationConnections).values({
|
|
62
|
+
workspaceId: params.workspaceId,
|
|
63
|
+
provider: params.provider,
|
|
64
|
+
externalAccountId: params.externalAccountId,
|
|
65
|
+
slug: params.slug,
|
|
66
|
+
displayName: params.displayName,
|
|
67
|
+
lifecycleStatus: params.lifecycleStatus ?? 'active'
|
|
68
|
+
}).returning();
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (isIntegrationConnectionUniqueViolation(error)) {
|
|
71
|
+
throw new IntegrationConnectionAlreadyExistsError(params.workspaceId, params.provider, params.externalAccountId);
|
|
72
|
+
}
|
|
73
|
+
if (isIntegrationConnectionSlugUniqueViolation(error)) {
|
|
74
|
+
throw new ConnectionSlugConflictError(error);
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
const row = rows[0];
|
|
79
|
+
if (!row) throw new Error('Integration connection insert returned no rows');
|
|
80
|
+
return toIntegrationConnection(row);
|
|
81
|
+
}
|
|
82
|
+
export async function resolveUniqueConnectionSlug(params, options = {}) {
|
|
83
|
+
const executor = options.tx ?? db();
|
|
84
|
+
const [existing] = await executor.select({
|
|
85
|
+
slug: integrationConnections.slug
|
|
86
|
+
}).from(integrationConnections).where(and(eq(integrationConnections.workspaceId, params.workspaceId), eq(integrationConnections.provider, params.provider), eq(integrationConnections.externalAccountId, params.externalAccountId))).limit(1);
|
|
87
|
+
if (existing) return existing.slug;
|
|
88
|
+
const workspaceSlugs = await executor.select({
|
|
89
|
+
slug: integrationConnections.slug
|
|
90
|
+
}).from(integrationConnections).where(eq(integrationConnections.workspaceId, params.workspaceId));
|
|
91
|
+
const used = new Set(workspaceSlugs.map((row)=>row.slug));
|
|
92
|
+
for(let suffixNumber = 1;; suffixNumber += 1){
|
|
93
|
+
const suffix = suffixNumber === 1 ? '' : `_${suffixNumber}`;
|
|
94
|
+
const baseBudget = CONNECTION_SLUG_MAX_LENGTH - suffix.length;
|
|
95
|
+
const candidate = `${params.baseSlug.slice(0, baseBudget).replaceAll(/[_-]+$/g, '')}${suffix}`;
|
|
96
|
+
if (!used.has(candidate)) return candidate;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export async function getIntegrationConnectionById(id, options = {}) {
|
|
100
|
+
const executor = options.tx ?? db();
|
|
101
|
+
const rows = await executor.select().from(integrationConnections).where(eq(integrationConnections.id, id)).limit(1);
|
|
102
|
+
const row = rows[0];
|
|
103
|
+
if (!row) return undefined;
|
|
104
|
+
return toIntegrationConnection(row);
|
|
105
|
+
}
|
|
106
|
+
export async function updateIntegrationConnectionLifecycleStatus(params, options = {}) {
|
|
107
|
+
const executor = options.tx ?? db();
|
|
108
|
+
const [row] = await executor.update(integrationConnections).set({
|
|
109
|
+
lifecycleStatus: params.lifecycleStatus,
|
|
110
|
+
updatedAt: new Date()
|
|
111
|
+
}).where(eq(integrationConnections.id, params.id)).returning();
|
|
112
|
+
if (!row) return undefined;
|
|
113
|
+
return toIntegrationConnection(row);
|
|
114
|
+
}
|
|
115
|
+
export async function deleteIntegrationConnection(params, options = {}) {
|
|
116
|
+
const executor = options.tx ?? db();
|
|
117
|
+
const result = await executor.delete(integrationConnections).where(eq(integrationConnections.id, params.id));
|
|
118
|
+
return (result.rowCount ?? 0) > 0;
|
|
119
|
+
}
|
|
120
|
+
export async function listIntegrationConnections(params) {
|
|
121
|
+
const rows = await db().select().from(integrationConnections).where(eq(integrationConnections.workspaceId, params.workspaceId)).orderBy(integrationConnections.createdAt, integrationConnections.id);
|
|
122
|
+
const connections = rows.map(toIntegrationConnection);
|
|
123
|
+
return connections;
|
|
124
|
+
}
|
|
125
|
+
export async function listIntegrationConnectionsByProvider(params) {
|
|
126
|
+
const rows = await db().select().from(integrationConnections).where(eq(integrationConnections.provider, params.provider)).orderBy(integrationConnections.createdAt, integrationConnections.id);
|
|
127
|
+
return rows.map(toIntegrationConnection);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/connections.ts"],"sourcesContent":["import {\n CONNECTION_SLUG_MAX_LENGTH,\n ConnectionSlugConflictError,\n} from '@shipfox/api-integration-core-dto';\nimport {and, eq} from 'drizzle-orm';\nimport type {\n IntegrationConnection,\n IntegrationConnectionLifecycleStatus,\n} from '#core/entities/connection.js';\nimport type {IntegrationProviderKind} from '#core/entities/provider.js';\nimport {IntegrationConnectionAlreadyExistsError} from '#core/errors.js';\nimport {db} from './db.js';\nimport {integrationConnections, toIntegrationConnection} from './schema/connections.js';\n\ntype IntegrationDb = ReturnType<typeof db>;\ntype IntegrationTx = Parameters<Parameters<IntegrationDb['transaction']>[0]>[0];\n\nexport interface UpsertIntegrationConnectionParams {\n workspaceId: string;\n provider: IntegrationProviderKind;\n externalAccountId: string;\n slug: string;\n displayName: string;\n lifecycleStatus?: IntegrationConnectionLifecycleStatus | undefined;\n}\n\nexport async function upsertIntegrationConnection(\n params: UpsertIntegrationConnectionParams,\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<IntegrationConnection> {\n const executor = options.tx ?? db();\n const now = new Date();\n const [row] = await executor\n .insert(integrationConnections)\n .values({\n workspaceId: params.workspaceId,\n provider: params.provider,\n externalAccountId: params.externalAccountId,\n slug: params.slug,\n displayName: params.displayName,\n lifecycleStatus: params.lifecycleStatus ?? 'active',\n })\n .onConflictDoUpdate({\n target: [\n integrationConnections.workspaceId,\n integrationConnections.provider,\n integrationConnections.externalAccountId,\n ],\n set: {\n displayName: params.displayName,\n lifecycleStatus: params.lifecycleStatus ?? 'active',\n updatedAt: now,\n },\n })\n .returning();\n\n if (!row) throw new Error('Integration connection upsert returned no rows');\n return toIntegrationConnection(row);\n}\n\nexport interface CreateIntegrationConnectionParams {\n workspaceId: string;\n provider: IntegrationProviderKind;\n externalAccountId: string;\n slug: string;\n displayName: string;\n lifecycleStatus?: IntegrationConnectionLifecycleStatus | undefined;\n}\n\nconst INTEGRATION_CONNECTION_EXTERNAL_UNIQUE_CONSTRAINT =\n 'integrations_connections_workspace_external_unique';\nconst INTEGRATION_CONNECTION_SLUG_UNIQUE_CONSTRAINT =\n 'integrations_connections_workspace_slug_unique';\n\nexport function isIntegrationConnectionUniqueViolation(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth += 1) {\n if (typeof current !== 'object') return false;\n const {code, constraint} = current as {code?: unknown; constraint?: unknown};\n if (code === '23505' && constraint === INTEGRATION_CONNECTION_EXTERNAL_UNIQUE_CONSTRAINT) {\n return true;\n }\n current = (current as {cause?: unknown}).cause;\n }\n return false;\n}\n\nexport function isIntegrationConnectionSlugUniqueViolation(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth += 1) {\n if (typeof current !== 'object') return false;\n const {code, constraint} = current as {code?: unknown; constraint?: unknown};\n if (code === '23505' && constraint === INTEGRATION_CONNECTION_SLUG_UNIQUE_CONSTRAINT) {\n return true;\n }\n current = (current as {cause?: unknown}).cause;\n }\n return false;\n}\n\nexport async function createIntegrationConnection(\n params: CreateIntegrationConnectionParams,\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<IntegrationConnection> {\n const executor = options.tx ?? db();\n let rows: (typeof integrationConnections.$inferSelect)[];\n try {\n rows = await executor\n .insert(integrationConnections)\n .values({\n workspaceId: params.workspaceId,\n provider: params.provider,\n externalAccountId: params.externalAccountId,\n slug: params.slug,\n displayName: params.displayName,\n lifecycleStatus: params.lifecycleStatus ?? 'active',\n })\n .returning();\n } catch (error) {\n if (isIntegrationConnectionUniqueViolation(error)) {\n throw new IntegrationConnectionAlreadyExistsError(\n params.workspaceId,\n params.provider,\n params.externalAccountId,\n );\n }\n if (isIntegrationConnectionSlugUniqueViolation(error)) {\n throw new ConnectionSlugConflictError(error);\n }\n throw error;\n }\n\n const row = rows[0];\n if (!row) throw new Error('Integration connection insert returned no rows');\n return toIntegrationConnection(row);\n}\n\nexport interface ResolveUniqueConnectionSlugParams {\n workspaceId: string;\n provider: IntegrationProviderKind;\n externalAccountId: string;\n baseSlug: string;\n}\n\nexport async function resolveUniqueConnectionSlug(\n params: ResolveUniqueConnectionSlugParams,\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<string> {\n const executor = options.tx ?? db();\n const [existing] = await executor\n .select({slug: integrationConnections.slug})\n .from(integrationConnections)\n .where(\n and(\n eq(integrationConnections.workspaceId, params.workspaceId),\n eq(integrationConnections.provider, params.provider),\n eq(integrationConnections.externalAccountId, params.externalAccountId),\n ),\n )\n .limit(1);\n if (existing) return existing.slug;\n\n const workspaceSlugs = await executor\n .select({slug: integrationConnections.slug})\n .from(integrationConnections)\n .where(eq(integrationConnections.workspaceId, params.workspaceId));\n const used = new Set(workspaceSlugs.map((row) => row.slug));\n\n for (let suffixNumber = 1; ; suffixNumber += 1) {\n const suffix = suffixNumber === 1 ? '' : `_${suffixNumber}`;\n const baseBudget = CONNECTION_SLUG_MAX_LENGTH - suffix.length;\n const candidate = `${params.baseSlug.slice(0, baseBudget).replaceAll(/[_-]+$/g, '')}${suffix}`;\n if (!used.has(candidate)) return candidate;\n }\n}\n\nexport type CreateIntegrationConnectionFn = typeof createIntegrationConnection;\n\nexport async function getIntegrationConnectionById(\n id: string,\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<IntegrationConnection | undefined> {\n const executor = options.tx ?? db();\n const rows = await executor\n .select()\n .from(integrationConnections)\n .where(eq(integrationConnections.id, id))\n .limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toIntegrationConnection(row);\n}\n\nexport type GetIntegrationConnectionByIdFn = typeof getIntegrationConnectionById;\n\nexport interface UpdateIntegrationConnectionLifecycleStatusParams {\n id: string;\n lifecycleStatus: IntegrationConnectionLifecycleStatus;\n}\n\nexport async function updateIntegrationConnectionLifecycleStatus(\n params: UpdateIntegrationConnectionLifecycleStatusParams,\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<IntegrationConnection | undefined> {\n const executor = options.tx ?? db();\n const [row] = await executor\n .update(integrationConnections)\n .set({lifecycleStatus: params.lifecycleStatus, updatedAt: new Date()})\n .where(eq(integrationConnections.id, params.id))\n .returning();\n if (!row) return undefined;\n return toIntegrationConnection(row);\n}\n\nexport type UpdateIntegrationConnectionLifecycleStatusFn =\n typeof updateIntegrationConnectionLifecycleStatus;\n\nexport async function deleteIntegrationConnection(\n params: {id: string},\n options: {tx?: IntegrationDb | IntegrationTx | undefined} = {},\n): Promise<boolean> {\n const executor = options.tx ?? db();\n const result = await executor\n .delete(integrationConnections)\n .where(eq(integrationConnections.id, params.id));\n return (result.rowCount ?? 0) > 0;\n}\n\nexport type DeleteIntegrationConnectionFn = typeof deleteIntegrationConnection;\n\nexport interface ListIntegrationConnectionsParams {\n workspaceId: string;\n}\n\nexport async function listIntegrationConnections(\n params: ListIntegrationConnectionsParams,\n): Promise<IntegrationConnection[]> {\n const rows = await db()\n .select()\n .from(integrationConnections)\n .where(eq(integrationConnections.workspaceId, params.workspaceId))\n .orderBy(integrationConnections.createdAt, integrationConnections.id);\n\n const connections = rows.map(toIntegrationConnection);\n return connections;\n}\n\nexport interface ListIntegrationConnectionsByProviderParams {\n provider: IntegrationProviderKind;\n}\n\nexport async function listIntegrationConnectionsByProvider(\n params: ListIntegrationConnectionsByProviderParams,\n): Promise<IntegrationConnection[]> {\n const rows = await db()\n .select()\n .from(integrationConnections)\n .where(eq(integrationConnections.provider, params.provider))\n .orderBy(integrationConnections.createdAt, integrationConnections.id);\n\n return rows.map(toIntegrationConnection);\n}\n"],"names":["CONNECTION_SLUG_MAX_LENGTH","ConnectionSlugConflictError","and","eq","IntegrationConnectionAlreadyExistsError","db","integrationConnections","toIntegrationConnection","upsertIntegrationConnection","params","options","executor","tx","now","Date","row","insert","values","workspaceId","provider","externalAccountId","slug","displayName","lifecycleStatus","onConflictDoUpdate","target","set","updatedAt","returning","Error","INTEGRATION_CONNECTION_EXTERNAL_UNIQUE_CONSTRAINT","INTEGRATION_CONNECTION_SLUG_UNIQUE_CONSTRAINT","isIntegrationConnectionUniqueViolation","error","current","depth","code","constraint","cause","isIntegrationConnectionSlugUniqueViolation","createIntegrationConnection","rows","resolveUniqueConnectionSlug","existing","select","from","where","limit","workspaceSlugs","used","Set","map","suffixNumber","suffix","baseBudget","length","candidate","baseSlug","slice","replaceAll","has","getIntegrationConnectionById","id","undefined","updateIntegrationConnectionLifecycleStatus","update","deleteIntegrationConnection","result","delete","rowCount","listIntegrationConnections","orderBy","createdAt","connections","listIntegrationConnectionsByProvider"],"mappings":"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"}
|