@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,109 @@
|
|
|
1
|
+
import { slugifyConnectionSlug } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { config } from '#config.js';
|
|
3
|
+
import { getIntegrationConnectionById, resolveUniqueConnectionSlug, upsertIntegrationConnection } from '#db/connections.js';
|
|
4
|
+
import { db } from '#db/db.js';
|
|
5
|
+
import { publishIntegrationEventReceived, publishSourcePush, recordDeliveryOnly } from '#db/webhook-deliveries.js';
|
|
6
|
+
import { retryConnectionSlugCollision } from '#providers/connection-slug.js';
|
|
7
|
+
// Stable migration-tracking table name for the GitHub provider database. This
|
|
8
|
+
// must NOT depend on the provider's position in the module `database` array. A
|
|
9
|
+
// positional name would shift if a provider is flag-disabled and silently
|
|
10
|
+
// re-run migrations against existing tables.
|
|
11
|
+
const GITHUB_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_github';
|
|
12
|
+
async function loadGithubModuleParts(options = {}) {
|
|
13
|
+
const { createGithubInstallationTokenProvider, createGithubE2eRoutes, encodeInstallationTokenEnvelope, createGithubIntegrationProvider, getGithubInstallationByInstallationId, githubInstallationTokenNamespace, db: githubDb, migrationsPath: githubMigrationsPath, upsertGithubInstallation } = await import('@shipfox/api-integration-github');
|
|
14
|
+
const tokenProvider = createGithubInstallationTokenProvider({
|
|
15
|
+
getIntegrationConnectionById,
|
|
16
|
+
secretStore: options.secrets?.github ? {
|
|
17
|
+
read: async (workspaceId, installationId)=>await options.secrets?.github?.getSecret({
|
|
18
|
+
workspaceId,
|
|
19
|
+
namespace: githubInstallationTokenNamespace(installationId),
|
|
20
|
+
key: 'envelope'
|
|
21
|
+
}) ?? null,
|
|
22
|
+
write: async (workspaceId, installationId, envelope)=>{
|
|
23
|
+
await options.secrets?.github?.setSecrets({
|
|
24
|
+
workspaceId,
|
|
25
|
+
namespace: githubInstallationTokenNamespace(installationId),
|
|
26
|
+
values: {
|
|
27
|
+
envelope: encodeInstallationTokenEnvelope(envelope)
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
} : undefined
|
|
32
|
+
});
|
|
33
|
+
async function getExistingGithubConnection(input) {
|
|
34
|
+
const installation = await getGithubInstallationByInstallationId(input.installationId);
|
|
35
|
+
if (!installation) return undefined;
|
|
36
|
+
const connection = await getIntegrationConnectionById(installation.connectionId);
|
|
37
|
+
if (!connection) return undefined;
|
|
38
|
+
return connection;
|
|
39
|
+
}
|
|
40
|
+
async function connectGithubInstallation(input) {
|
|
41
|
+
return await retryConnectionSlugCollision(()=>db().transaction(async (tx)=>{
|
|
42
|
+
const baseSlug = slugifyConnectionSlug(`github_${input.installation.accountLogin}`, {
|
|
43
|
+
fallback: 'github'
|
|
44
|
+
});
|
|
45
|
+
const slug = await resolveUniqueConnectionSlug({
|
|
46
|
+
workspaceId: input.workspaceId,
|
|
47
|
+
provider: 'github',
|
|
48
|
+
externalAccountId: input.installationId,
|
|
49
|
+
baseSlug
|
|
50
|
+
}, {
|
|
51
|
+
tx
|
|
52
|
+
});
|
|
53
|
+
const connection = await upsertIntegrationConnection({
|
|
54
|
+
workspaceId: input.workspaceId,
|
|
55
|
+
provider: 'github',
|
|
56
|
+
externalAccountId: input.installationId,
|
|
57
|
+
slug,
|
|
58
|
+
displayName: input.displayName,
|
|
59
|
+
lifecycleStatus: 'active'
|
|
60
|
+
}, {
|
|
61
|
+
tx
|
|
62
|
+
});
|
|
63
|
+
await upsertGithubInstallation({
|
|
64
|
+
connectionId: connection.id,
|
|
65
|
+
...input.installation
|
|
66
|
+
}, {
|
|
67
|
+
tx
|
|
68
|
+
});
|
|
69
|
+
return connection;
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
provider: createGithubIntegrationProvider({
|
|
74
|
+
getExistingGithubConnection,
|
|
75
|
+
connectGithubInstallation,
|
|
76
|
+
publishIntegrationEventReceived,
|
|
77
|
+
publishSourcePush,
|
|
78
|
+
recordDeliveryOnly,
|
|
79
|
+
getIntegrationConnectionById,
|
|
80
|
+
coreDb: db,
|
|
81
|
+
deleteSecrets: options.secrets?.deleteSecrets,
|
|
82
|
+
agentTools: {
|
|
83
|
+
tokenProvider
|
|
84
|
+
}
|
|
85
|
+
}),
|
|
86
|
+
e2eRoutes: [
|
|
87
|
+
createGithubE2eRoutes({
|
|
88
|
+
getExistingGithubConnection,
|
|
89
|
+
connectGithubInstallation,
|
|
90
|
+
connectionCapabilities: [
|
|
91
|
+
'source_control',
|
|
92
|
+
'agent_tools'
|
|
93
|
+
]
|
|
94
|
+
})
|
|
95
|
+
],
|
|
96
|
+
database: {
|
|
97
|
+
db: githubDb,
|
|
98
|
+
migrationsPath: githubMigrationsPath,
|
|
99
|
+
migrationsTableName: GITHUB_MIGRATIONS_TABLE
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export const githubProviderModule = {
|
|
104
|
+
id: 'github',
|
|
105
|
+
enabled: config.INTEGRATIONS_ENABLE_GITHUB_PROVIDER,
|
|
106
|
+
load: loadGithubModuleParts
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/github.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectGithubInstallationInput} from '@shipfox/api-integration-github';\nimport {config} from '#config.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {\n publishIntegrationEventReceived,\n publishSourcePush,\n recordDeliveryOnly,\n} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModule,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\n\n// Stable migration-tracking table name for the GitHub provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst GITHUB_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_github';\n\nasync function loadGithubModuleParts(\n options: IntegrationProviderModuleLoadOptions = {},\n): Promise<IntegrationModuleParts> {\n const {\n createGithubInstallationTokenProvider,\n createGithubE2eRoutes,\n encodeInstallationTokenEnvelope,\n createGithubIntegrationProvider,\n getGithubInstallationByInstallationId,\n githubInstallationTokenNamespace,\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n upsertGithubInstallation,\n } = await import('@shipfox/api-integration-github');\n\n const tokenProvider = createGithubInstallationTokenProvider({\n getIntegrationConnectionById,\n secretStore: options.secrets?.github\n ? {\n read: async (workspaceId, installationId) =>\n (await options.secrets?.github?.getSecret({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n key: 'envelope',\n })) ?? null,\n write: async (workspaceId, installationId, envelope) => {\n await options.secrets?.github?.setSecrets({\n workspaceId,\n namespace: githubInstallationTokenNamespace(installationId),\n values: {envelope: encodeInstallationTokenEnvelope(envelope)},\n });\n },\n }\n : undefined,\n });\n\n async function getExistingGithubConnection(input: {\n installationId: string;\n }): Promise<CoreIntegrationConnection<'github'> | undefined> {\n const installation = await getGithubInstallationByInstallationId(input.installationId);\n if (!installation) return undefined;\n const connection = await getIntegrationConnectionById(installation.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'github'>;\n }\n\n async function connectGithubInstallation(\n input: ConnectGithubInstallationInput,\n ): Promise<CoreIntegrationConnection<'github'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`github_${input.installation.accountLogin}`, {\n fallback: 'github',\n });\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'github',\n externalAccountId: input.installationId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n\n await upsertGithubInstallation(\n {\n connectionId: connection.id,\n ...input.installation,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'github'>;\n }),\n );\n }\n\n return {\n provider: createGithubIntegrationProvider({\n getExistingGithubConnection,\n connectGithubInstallation,\n publishIntegrationEventReceived,\n publishSourcePush,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n deleteSecrets: options.secrets?.deleteSecrets,\n agentTools: {tokenProvider},\n }),\n e2eRoutes: [\n createGithubE2eRoutes({\n getExistingGithubConnection,\n connectGithubInstallation,\n connectionCapabilities: ['source_control', 'agent_tools'],\n }),\n ],\n database: {\n db: githubDb,\n migrationsPath: githubMigrationsPath,\n migrationsTableName: GITHUB_MIGRATIONS_TABLE,\n },\n };\n}\n\nexport const githubProviderModule: IntegrationProviderModule = {\n id: 'github',\n enabled: config.INTEGRATIONS_ENABLE_GITHUB_PROVIDER,\n load: loadGithubModuleParts,\n};\n"],"names":["slugifyConnectionSlug","config","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishIntegrationEventReceived","publishSourcePush","recordDeliveryOnly","retryConnectionSlugCollision","GITHUB_MIGRATIONS_TABLE","loadGithubModuleParts","options","createGithubInstallationTokenProvider","createGithubE2eRoutes","encodeInstallationTokenEnvelope","createGithubIntegrationProvider","getGithubInstallationByInstallationId","githubInstallationTokenNamespace","githubDb","migrationsPath","githubMigrationsPath","upsertGithubInstallation","tokenProvider","secretStore","secrets","github","read","workspaceId","installationId","getSecret","namespace","key","write","envelope","setSecrets","values","undefined","getExistingGithubConnection","input","installation","connection","connectionId","connectGithubInstallation","transaction","tx","baseSlug","accountLogin","fallback","slug","provider","externalAccountId","displayName","lifecycleStatus","id","coreDb","deleteSecrets","agentTools","e2eRoutes","connectionCapabilities","database","migrationsTableName","githubProviderModule","enabled","INTEGRATIONS_ENABLE_GITHUB_PROVIDER","load"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../../src/providers/linear.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAqJ3F,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { slugifyConnectionSlug } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { config } from '#config.js';
|
|
3
|
+
import { deleteIntegrationConnection, getIntegrationConnectionById, resolveUniqueConnectionSlug, upsertIntegrationConnection } from '#db/connections.js';
|
|
4
|
+
import { db } from '#db/db.js';
|
|
5
|
+
import { publishIntegrationEventReceived, recordDeliveryOnly } from '#db/webhook-deliveries.js';
|
|
6
|
+
import { retryConnectionSlugCollision } from '#providers/connection-slug.js';
|
|
7
|
+
const LINEAR_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_linear';
|
|
8
|
+
const LINEAR_SECRETS_NAMESPACE_PREFIX = 'system/integrations/linear/';
|
|
9
|
+
async function loadLinearModuleParts(options = {}) {
|
|
10
|
+
const { createLinearTokenStore, createLinearE2eRoutes, createLinearIntegrationProvider, config: linearConfig, disconnectLinearInstallation: disconnectLinearInstallationRecords, getLinearInstallationByOrganizationId, db: linearDb, migrationsPath: linearMigrationsPath, upsertLinearInstallation } = await import('@shipfox/api-integration-linear');
|
|
11
|
+
async function getExistingLinearConnection(input) {
|
|
12
|
+
const installation = await getLinearInstallationByOrganizationId(input.organizationId);
|
|
13
|
+
if (!installation) return undefined;
|
|
14
|
+
const connection = await getIntegrationConnectionById(installation.connectionId);
|
|
15
|
+
if (!connection) return undefined;
|
|
16
|
+
return connection;
|
|
17
|
+
}
|
|
18
|
+
async function connectLinearInstallation(input) {
|
|
19
|
+
return await retryConnectionSlugCollision(()=>db().transaction(async (tx)=>{
|
|
20
|
+
const baseSlug = slugifyConnectionSlug(`linear_${input.organizationUrlKey}`, {
|
|
21
|
+
fallback: 'linear'
|
|
22
|
+
});
|
|
23
|
+
const slug = await resolveUniqueConnectionSlug({
|
|
24
|
+
workspaceId: input.workspaceId,
|
|
25
|
+
provider: 'linear',
|
|
26
|
+
externalAccountId: input.organizationId,
|
|
27
|
+
baseSlug
|
|
28
|
+
}, {
|
|
29
|
+
tx
|
|
30
|
+
});
|
|
31
|
+
const connection = await upsertIntegrationConnection({
|
|
32
|
+
workspaceId: input.workspaceId,
|
|
33
|
+
provider: 'linear',
|
|
34
|
+
externalAccountId: input.organizationId,
|
|
35
|
+
slug,
|
|
36
|
+
displayName: input.displayName,
|
|
37
|
+
lifecycleStatus: 'active'
|
|
38
|
+
}, {
|
|
39
|
+
tx
|
|
40
|
+
});
|
|
41
|
+
await upsertLinearInstallation({
|
|
42
|
+
connectionId: connection.id,
|
|
43
|
+
organizationId: input.organizationId,
|
|
44
|
+
organizationUrlKey: input.organizationUrlKey,
|
|
45
|
+
appUserId: input.appUserId,
|
|
46
|
+
scopes: input.scopes,
|
|
47
|
+
tokenExpiresAt: input.tokenExpiresAt,
|
|
48
|
+
status: 'installed'
|
|
49
|
+
}, {
|
|
50
|
+
tx
|
|
51
|
+
});
|
|
52
|
+
return connection;
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
async function disconnectLinearInstallation(input) {
|
|
56
|
+
await disconnectLinearInstallationRecords({
|
|
57
|
+
connectionId: input.connectionId,
|
|
58
|
+
getConnection: getIntegrationConnectionById,
|
|
59
|
+
deleteSecrets: (params)=>options.secrets?.linear?.deleteSecrets({
|
|
60
|
+
...params,
|
|
61
|
+
namespace: linearNamespaceSuffix(params.namespace)
|
|
62
|
+
}) ?? Promise.resolve(0),
|
|
63
|
+
transaction: (fn)=>db().transaction((tx)=>fn(tx)),
|
|
64
|
+
deleteConnection: (params, options)=>deleteIntegrationConnection({
|
|
65
|
+
id: params.connectionId
|
|
66
|
+
}, options)
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const fallbackSecrets = {
|
|
70
|
+
getSecret: ()=>Promise.resolve(null),
|
|
71
|
+
setSecrets: ()=>Promise.reject(new Error('Linear token storage is not configured'))
|
|
72
|
+
};
|
|
73
|
+
const secrets = options.secrets?.linear ? {
|
|
74
|
+
getSecret: (params)=>options.secrets?.linear?.getSecret({
|
|
75
|
+
...params,
|
|
76
|
+
namespace: linearNamespaceSuffix(params.namespace)
|
|
77
|
+
}) ?? Promise.resolve(null),
|
|
78
|
+
setSecrets: (params)=>options.secrets?.linear?.setSecrets({
|
|
79
|
+
...params,
|
|
80
|
+
namespace: linearNamespaceSuffix(params.namespace)
|
|
81
|
+
}) ?? Promise.resolve()
|
|
82
|
+
} : fallbackSecrets;
|
|
83
|
+
const tokenStore = createLinearTokenStore({
|
|
84
|
+
resolveConnection: async (connectionId)=>getIntegrationConnectionById(connectionId),
|
|
85
|
+
secrets
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
provider: createLinearIntegrationProvider({
|
|
89
|
+
agentTools: {
|
|
90
|
+
tokenStore,
|
|
91
|
+
endpoint: linearConfig.LINEAR_MCP_ENDPOINT
|
|
92
|
+
},
|
|
93
|
+
routes: {
|
|
94
|
+
tokenStore,
|
|
95
|
+
getExistingLinearConnection,
|
|
96
|
+
connectLinearInstallation,
|
|
97
|
+
disconnectLinearInstallation,
|
|
98
|
+
publishIntegrationEventReceived,
|
|
99
|
+
recordDeliveryOnly,
|
|
100
|
+
getIntegrationConnectionById,
|
|
101
|
+
coreDb: db
|
|
102
|
+
}
|
|
103
|
+
}),
|
|
104
|
+
e2eRoutes: [
|
|
105
|
+
createLinearE2eRoutes({
|
|
106
|
+
tokenStore,
|
|
107
|
+
getExistingLinearConnection,
|
|
108
|
+
connectLinearInstallation,
|
|
109
|
+
disconnectLinearInstallation,
|
|
110
|
+
connectionCapabilities: [
|
|
111
|
+
'agent_tools'
|
|
112
|
+
]
|
|
113
|
+
})
|
|
114
|
+
],
|
|
115
|
+
database: {
|
|
116
|
+
db: linearDb,
|
|
117
|
+
migrationsPath: linearMigrationsPath,
|
|
118
|
+
migrationsTableName: LINEAR_MIGRATIONS_TABLE
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export const linearProviderModule = {
|
|
123
|
+
id: 'linear',
|
|
124
|
+
enabled: config.INTEGRATIONS_ENABLE_LINEAR_PROVIDER,
|
|
125
|
+
load: loadLinearModuleParts
|
|
126
|
+
};
|
|
127
|
+
function linearNamespaceSuffix(namespace) {
|
|
128
|
+
if (!namespace.startsWith(LINEAR_SECRETS_NAMESPACE_PREFIX)) {
|
|
129
|
+
throw new Error('Linear provider attempted to access an unscoped secret namespace');
|
|
130
|
+
}
|
|
131
|
+
return namespace.slice(LINEAR_SECRETS_NAMESPACE_PREFIX.length);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=linear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/linear.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {\n ConnectLinearInstallationInput,\n LinearSecretsStore,\n} from '@shipfox/api-integration-linear';\nimport {config} from '#config.js';\nimport {\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {publishIntegrationEventReceived, recordDeliveryOnly} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\nconst LINEAR_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_linear';\nconst LINEAR_SECRETS_NAMESPACE_PREFIX = 'system/integrations/linear/';\n\ntype IntegrationDb = ReturnType<typeof db>;\ntype IntegrationTx = Parameters<Parameters<IntegrationDb['transaction']>[0]>[0];\n\nasync function loadLinearModuleParts(\n options: Parameters<IntegrationProviderModule['load']>[0] = {},\n): Promise<IntegrationModuleParts> {\n const {\n createLinearTokenStore,\n createLinearE2eRoutes,\n createLinearIntegrationProvider,\n config: linearConfig,\n disconnectLinearInstallation: disconnectLinearInstallationRecords,\n getLinearInstallationByOrganizationId,\n db: linearDb,\n migrationsPath: linearMigrationsPath,\n upsertLinearInstallation,\n } = await import('@shipfox/api-integration-linear');\n\n async function getExistingLinearConnection(input: {\n organizationId: string;\n }): Promise<CoreIntegrationConnection<'linear'> | undefined> {\n const installation = await getLinearInstallationByOrganizationId(input.organizationId);\n if (!installation) return undefined;\n const connection = await getIntegrationConnectionById(installation.connectionId);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'linear'>;\n }\n\n async function connectLinearInstallation(\n input: ConnectLinearInstallationInput,\n ): Promise<CoreIntegrationConnection<'linear'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`linear_${input.organizationUrlKey}`, {\n fallback: 'linear',\n });\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'linear',\n externalAccountId: input.organizationId,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'linear',\n externalAccountId: input.organizationId,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n\n await upsertLinearInstallation(\n {\n connectionId: connection.id,\n organizationId: input.organizationId,\n organizationUrlKey: input.organizationUrlKey,\n appUserId: input.appUserId,\n scopes: input.scopes,\n tokenExpiresAt: input.tokenExpiresAt,\n status: 'installed',\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'linear'>;\n }),\n );\n }\n\n async function disconnectLinearInstallation(input: {connectionId: string}): Promise<void> {\n await disconnectLinearInstallationRecords<IntegrationTx>({\n connectionId: input.connectionId,\n getConnection: getIntegrationConnectionById,\n deleteSecrets: (params) =>\n options.secrets?.linear?.deleteSecrets({\n ...params,\n namespace: linearNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(0),\n transaction: (fn) => db().transaction((tx) => fn(tx)),\n deleteConnection: (params, options) =>\n deleteIntegrationConnection({id: params.connectionId}, options),\n });\n }\n\n const fallbackSecrets: LinearSecretsStore = {\n getSecret: () => Promise.resolve(null),\n setSecrets: () => Promise.reject(new Error('Linear token storage is not configured')),\n };\n const secrets: LinearSecretsStore = options.secrets?.linear\n ? {\n getSecret: (params: Parameters<LinearSecretsStore['getSecret']>[0]) =>\n options.secrets?.linear?.getSecret({\n ...params,\n namespace: linearNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(null),\n setSecrets: (params: Parameters<LinearSecretsStore['setSecrets']>[0]) =>\n options.secrets?.linear?.setSecrets({\n ...params,\n namespace: linearNamespaceSuffix(params.namespace),\n }) ?? Promise.resolve(),\n }\n : fallbackSecrets;\n const tokenStore = createLinearTokenStore({\n resolveConnection: async (connectionId) => getIntegrationConnectionById(connectionId),\n secrets,\n });\n\n return {\n provider: createLinearIntegrationProvider({\n agentTools: {tokenStore, endpoint: linearConfig.LINEAR_MCP_ENDPOINT},\n routes: {\n tokenStore,\n getExistingLinearConnection,\n connectLinearInstallation,\n disconnectLinearInstallation,\n publishIntegrationEventReceived,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n coreDb: db,\n },\n }),\n e2eRoutes: [\n createLinearE2eRoutes({\n tokenStore,\n getExistingLinearConnection,\n connectLinearInstallation,\n disconnectLinearInstallation,\n connectionCapabilities: ['agent_tools'],\n }),\n ],\n database: {\n db: linearDb,\n migrationsPath: linearMigrationsPath,\n migrationsTableName: LINEAR_MIGRATIONS_TABLE,\n },\n };\n}\n\nexport const linearProviderModule: IntegrationProviderModule = {\n id: 'linear',\n enabled: config.INTEGRATIONS_ENABLE_LINEAR_PROVIDER,\n load: loadLinearModuleParts,\n};\n\nfunction linearNamespaceSuffix(namespace: string): string {\n if (!namespace.startsWith(LINEAR_SECRETS_NAMESPACE_PREFIX)) {\n throw new Error('Linear provider attempted to access an unscoped secret namespace');\n }\n return namespace.slice(LINEAR_SECRETS_NAMESPACE_PREFIX.length);\n}\n"],"names":["slugifyConnectionSlug","config","deleteIntegrationConnection","getIntegrationConnectionById","resolveUniqueConnectionSlug","upsertIntegrationConnection","db","publishIntegrationEventReceived","recordDeliveryOnly","retryConnectionSlugCollision","LINEAR_MIGRATIONS_TABLE","LINEAR_SECRETS_NAMESPACE_PREFIX","loadLinearModuleParts","options","createLinearTokenStore","createLinearE2eRoutes","createLinearIntegrationProvider","linearConfig","disconnectLinearInstallation","disconnectLinearInstallationRecords","getLinearInstallationByOrganizationId","linearDb","migrationsPath","linearMigrationsPath","upsertLinearInstallation","getExistingLinearConnection","input","installation","organizationId","undefined","connection","connectionId","connectLinearInstallation","transaction","tx","baseSlug","organizationUrlKey","fallback","slug","workspaceId","provider","externalAccountId","displayName","lifecycleStatus","id","appUserId","scopes","tokenExpiresAt","status","getConnection","deleteSecrets","params","secrets","linear","namespace","linearNamespaceSuffix","Promise","resolve","fn","deleteConnection","fallbackSecrets","getSecret","setSecrets","reject","Error","tokenStore","resolveConnection","agentTools","endpoint","LINEAR_MCP_ENDPOINT","routes","coreDb","e2eRoutes","connectionCapabilities","database","migrationsTableName","linearProviderModule","enabled","INTEGRATIONS_ENABLE_LINEAR_PROVIDER","load","startsWith","slice","length"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { IntegrationModuleParts, IntegrationProviderModuleLoadOptions } from '#providers/types.js';
|
|
2
|
+
export declare function loadEnabledProviderModules(options?: IntegrationProviderModuleLoadOptions): Promise<IntegrationModuleParts[]>;
|
|
3
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../src/providers/modules.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,oCAAoC,EACrC,MAAM,qBAAqB,CAAC;AAc7B,wBAAsB,0BAA0B,CAC9C,OAAO,GAAE,oCAAyC,GACjD,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAOnC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { cronProviderModule } from '#providers/cron.js';
|
|
2
|
+
import { giteaProviderModule } from '#providers/gitea.js';
|
|
3
|
+
import { githubProviderModule } from '#providers/github.js';
|
|
4
|
+
import { linearProviderModule } from '#providers/linear.js';
|
|
5
|
+
import { sentryProviderModule } from '#providers/sentry.js';
|
|
6
|
+
import { webhookProviderModule } from '#providers/webhook.js';
|
|
7
|
+
// Order is significant: databases are migrated in this order, so list a provider
|
|
8
|
+
// before any that depend on its tables.
|
|
9
|
+
const providerModules = [
|
|
10
|
+
githubProviderModule,
|
|
11
|
+
linearProviderModule,
|
|
12
|
+
sentryProviderModule,
|
|
13
|
+
giteaProviderModule,
|
|
14
|
+
cronProviderModule,
|
|
15
|
+
webhookProviderModule
|
|
16
|
+
];
|
|
17
|
+
export async function loadEnabledProviderModules(options = {}) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
for (const module of providerModules){
|
|
20
|
+
if (!module.enabled) continue;
|
|
21
|
+
parts.push(await module.load(options));
|
|
22
|
+
}
|
|
23
|
+
return parts;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/modules.ts"],"sourcesContent":["import {cronProviderModule} from '#providers/cron.js';\nimport {giteaProviderModule} from '#providers/gitea.js';\nimport {githubProviderModule} from '#providers/github.js';\nimport {linearProviderModule} from '#providers/linear.js';\nimport {sentryProviderModule} from '#providers/sentry.js';\nimport type {\n IntegrationModuleParts,\n IntegrationProviderModuleLoadOptions,\n} from '#providers/types.js';\nimport {webhookProviderModule} from '#providers/webhook.js';\n\n// Order is significant: databases are migrated in this order, so list a provider\n// before any that depend on its tables.\nconst providerModules = [\n githubProviderModule,\n linearProviderModule,\n sentryProviderModule,\n giteaProviderModule,\n cronProviderModule,\n webhookProviderModule,\n];\n\nexport async function loadEnabledProviderModules(\n options: IntegrationProviderModuleLoadOptions = {},\n): Promise<IntegrationModuleParts[]> {\n const parts: IntegrationModuleParts[] = [];\n for (const module of providerModules) {\n if (!module.enabled) continue;\n parts.push(await module.load(options));\n }\n return parts;\n}\n"],"names":["cronProviderModule","giteaProviderModule","githubProviderModule","linearProviderModule","sentryProviderModule","webhookProviderModule","providerModules","loadEnabledProviderModules","options","parts","module","enabled","push","load"],"mappings":"AAAA,SAAQA,kBAAkB,QAAO,qBAAqB;AACtD,SAAQC,mBAAmB,QAAO,sBAAsB;AACxD,SAAQC,oBAAoB,QAAO,uBAAuB;AAC1D,SAAQC,oBAAoB,QAAO,uBAAuB;AAC1D,SAAQC,oBAAoB,QAAO,uBAAuB;AAK1D,SAAQC,qBAAqB,QAAO,wBAAwB;AAE5D,iFAAiF;AACjF,wCAAwC;AACxC,MAAMC,kBAAkB;IACtBJ;IACAC;IACAC;IACAH;IACAD;IACAK;CACD;AAED,OAAO,eAAeE,2BACpBC,UAAgD,CAAC,CAAC;IAElD,MAAMC,QAAkC,EAAE;IAC1C,KAAK,MAAMC,UAAUJ,gBAAiB;QACpC,IAAI,CAACI,OAAOC,OAAO,EAAE;QACrBF,MAAMG,IAAI,CAAC,MAAMF,OAAOG,IAAI,CAACL;IAC/B;IACA,OAAOC;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry.d.ts","sourceRoot":"","sources":["../../src/providers/sentry.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAyB,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AA6F3F,eAAO,MAAM,oBAAoB,EAAE,yBAIlC,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { slugifyConnectionSlug } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { config } from '#config.js';
|
|
3
|
+
import { getIntegrationConnectionById, resolveUniqueConnectionSlug, updateIntegrationConnectionLifecycleStatus, upsertIntegrationConnection } from '#db/connections.js';
|
|
4
|
+
import { db } from '#db/db.js';
|
|
5
|
+
import { publishIntegrationEventReceived, recordDeliveryOnly } from '#db/webhook-deliveries.js';
|
|
6
|
+
import { retryConnectionSlugCollision } from '#providers/connection-slug.js';
|
|
7
|
+
// Stable migration-tracking table name for the Sentry provider database. This
|
|
8
|
+
// must NOT depend on the provider's position in the module `database` array. A
|
|
9
|
+
// positional name would shift if a provider is flag-disabled and silently
|
|
10
|
+
// re-run migrations against existing tables.
|
|
11
|
+
const SENTRY_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_sentry';
|
|
12
|
+
async function loadSentryModuleParts() {
|
|
13
|
+
const { createSentryIntegrationProvider, createSentryMaintenanceWorker, getSentryInstallationByInstallationUuid, persistVerifiedUnclaimedInstallation, upsertSentryInstallation, db: sentryDb, migrationsPath: sentryMigrationsPath } = await import('@shipfox/api-integration-sentry');
|
|
14
|
+
async function getConnectionById(id) {
|
|
15
|
+
const connection = await getIntegrationConnectionById(id);
|
|
16
|
+
if (!connection) return undefined;
|
|
17
|
+
return connection;
|
|
18
|
+
}
|
|
19
|
+
async function connectSentryInstallation(input) {
|
|
20
|
+
return await retryConnectionSlugCollision(()=>db().transaction(async (tx)=>{
|
|
21
|
+
const baseSlug = slugifyConnectionSlug(`sentry_${input.orgSlug}`, {
|
|
22
|
+
fallback: 'sentry'
|
|
23
|
+
});
|
|
24
|
+
const slug = await resolveUniqueConnectionSlug({
|
|
25
|
+
workspaceId: input.workspaceId,
|
|
26
|
+
provider: 'sentry',
|
|
27
|
+
externalAccountId: input.installationUuid,
|
|
28
|
+
baseSlug
|
|
29
|
+
}, {
|
|
30
|
+
tx
|
|
31
|
+
});
|
|
32
|
+
const connection = await upsertIntegrationConnection({
|
|
33
|
+
workspaceId: input.workspaceId,
|
|
34
|
+
provider: 'sentry',
|
|
35
|
+
externalAccountId: input.installationUuid,
|
|
36
|
+
slug,
|
|
37
|
+
displayName: input.displayName,
|
|
38
|
+
lifecycleStatus: 'active'
|
|
39
|
+
}, {
|
|
40
|
+
tx
|
|
41
|
+
});
|
|
42
|
+
await upsertSentryInstallation({
|
|
43
|
+
connectionId: connection.id,
|
|
44
|
+
installationUuid: input.installationUuid,
|
|
45
|
+
orgSlug: input.orgSlug,
|
|
46
|
+
status: 'installed',
|
|
47
|
+
codeHash: input.codeHash,
|
|
48
|
+
installerUserId: input.installerUserId
|
|
49
|
+
}, {
|
|
50
|
+
tx
|
|
51
|
+
});
|
|
52
|
+
return connection;
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
provider: createSentryIntegrationProvider({
|
|
57
|
+
getSentryInstallation: ({ installationUuid })=>getSentryInstallationByInstallationUuid(installationUuid),
|
|
58
|
+
getConnectionById,
|
|
59
|
+
connectSentryInstallation,
|
|
60
|
+
persistVerifiedUnclaimedInstallation,
|
|
61
|
+
coreDb: db,
|
|
62
|
+
publishIntegrationEventReceived,
|
|
63
|
+
recordDeliveryOnly,
|
|
64
|
+
getIntegrationConnectionById,
|
|
65
|
+
updateConnectionLifecycleStatus: updateIntegrationConnectionLifecycleStatus
|
|
66
|
+
}),
|
|
67
|
+
database: {
|
|
68
|
+
db: sentryDb,
|
|
69
|
+
migrationsPath: sentryMigrationsPath,
|
|
70
|
+
migrationsTableName: SENTRY_MIGRATIONS_TABLE
|
|
71
|
+
},
|
|
72
|
+
workers: [
|
|
73
|
+
createSentryMaintenanceWorker()
|
|
74
|
+
]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export const sentryProviderModule = {
|
|
78
|
+
id: 'sentry',
|
|
79
|
+
enabled: config.INTEGRATIONS_ENABLE_SENTRY_PROVIDER,
|
|
80
|
+
load: loadSentryModuleParts
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=sentry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/sentry.ts"],"sourcesContent":["import {\n type IntegrationConnection as CoreIntegrationConnection,\n slugifyConnectionSlug,\n} from '@shipfox/api-integration-core-dto';\nimport type {ConnectSentryInstallationInput} from '@shipfox/api-integration-sentry';\nimport {config} from '#config.js';\nimport {\n getIntegrationConnectionById,\n resolveUniqueConnectionSlug,\n updateIntegrationConnectionLifecycleStatus,\n upsertIntegrationConnection,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {publishIntegrationEventReceived, recordDeliveryOnly} from '#db/webhook-deliveries.js';\nimport {retryConnectionSlugCollision} from '#providers/connection-slug.js';\nimport type {IntegrationModuleParts, IntegrationProviderModule} from '#providers/types.js';\n\n// Stable migration-tracking table name for the Sentry provider database. This\n// must NOT depend on the provider's position in the module `database` array. A\n// positional name would shift if a provider is flag-disabled and silently\n// re-run migrations against existing tables.\nconst SENTRY_MIGRATIONS_TABLE = '__drizzle_migrations_integrations_sentry';\n\nasync function loadSentryModuleParts(): Promise<IntegrationModuleParts> {\n const {\n createSentryIntegrationProvider,\n createSentryMaintenanceWorker,\n getSentryInstallationByInstallationUuid,\n persistVerifiedUnclaimedInstallation,\n upsertSentryInstallation,\n db: sentryDb,\n migrationsPath: sentryMigrationsPath,\n } = await import('@shipfox/api-integration-sentry');\n\n async function getConnectionById(\n id: string,\n ): Promise<CoreIntegrationConnection<'sentry'> | undefined> {\n const connection = await getIntegrationConnectionById(id);\n if (!connection) return undefined;\n return connection as CoreIntegrationConnection<'sentry'>;\n }\n\n async function connectSentryInstallation(\n input: ConnectSentryInstallationInput,\n ): Promise<CoreIntegrationConnection<'sentry'>> {\n return await retryConnectionSlugCollision(() =>\n db().transaction(async (tx) => {\n const baseSlug = slugifyConnectionSlug(`sentry_${input.orgSlug}`, {fallback: 'sentry'});\n const slug = await resolveUniqueConnectionSlug(\n {\n workspaceId: input.workspaceId,\n provider: 'sentry',\n externalAccountId: input.installationUuid,\n baseSlug,\n },\n {tx},\n );\n const connection = await upsertIntegrationConnection(\n {\n workspaceId: input.workspaceId,\n provider: 'sentry',\n externalAccountId: input.installationUuid,\n slug,\n displayName: input.displayName,\n lifecycleStatus: 'active',\n },\n {tx},\n );\n\n await upsertSentryInstallation(\n {\n connectionId: connection.id,\n installationUuid: input.installationUuid,\n orgSlug: input.orgSlug,\n status: 'installed',\n codeHash: input.codeHash,\n installerUserId: input.installerUserId,\n },\n {tx},\n );\n\n return connection as CoreIntegrationConnection<'sentry'>;\n }),\n );\n }\n\n return {\n provider: createSentryIntegrationProvider({\n getSentryInstallation: ({installationUuid}) =>\n getSentryInstallationByInstallationUuid(installationUuid),\n getConnectionById,\n connectSentryInstallation,\n persistVerifiedUnclaimedInstallation,\n coreDb: db,\n publishIntegrationEventReceived,\n recordDeliveryOnly,\n getIntegrationConnectionById,\n updateConnectionLifecycleStatus: updateIntegrationConnectionLifecycleStatus,\n }),\n database: {\n db: sentryDb,\n migrationsPath: sentryMigrationsPath,\n migrationsTableName: SENTRY_MIGRATIONS_TABLE,\n },\n workers: [createSentryMaintenanceWorker()],\n };\n}\n\nexport const sentryProviderModule: IntegrationProviderModule = {\n id: 'sentry',\n enabled: config.INTEGRATIONS_ENABLE_SENTRY_PROVIDER,\n load: loadSentryModuleParts,\n};\n"],"names":["slugifyConnectionSlug","config","getIntegrationConnectionById","resolveUniqueConnectionSlug","updateIntegrationConnectionLifecycleStatus","upsertIntegrationConnection","db","publishIntegrationEventReceived","recordDeliveryOnly","retryConnectionSlugCollision","SENTRY_MIGRATIONS_TABLE","loadSentryModuleParts","createSentryIntegrationProvider","createSentryMaintenanceWorker","getSentryInstallationByInstallationUuid","persistVerifiedUnclaimedInstallation","upsertSentryInstallation","sentryDb","migrationsPath","sentryMigrationsPath","getConnectionById","id","connection","undefined","connectSentryInstallation","input","transaction","tx","baseSlug","orgSlug","fallback","slug","workspaceId","provider","externalAccountId","installationUuid","displayName","lifecycleStatus","connectionId","status","codeHash","installerUserId","getSentryInstallation","coreDb","updateConnectionLifecycleStatus","database","migrationsTableName","workers","sentryProviderModule","enabled","INTEGRATIONS_ENABLE_SENTRY_PROVIDER","load"],"mappings":"AAAA,SAEEA,qBAAqB,QAChB,oCAAoC;AAE3C,SAAQC,MAAM,QAAO,aAAa;AAClC,SACEC,4BAA4B,EAC5BC,2BAA2B,EAC3BC,0CAA0C,EAC1CC,2BAA2B,QACtB,qBAAqB;AAC5B,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,+BAA+B,EAAEC,kBAAkB,QAAO,4BAA4B;AAC9F,SAAQC,4BAA4B,QAAO,gCAAgC;AAG3E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAC1E,6CAA6C;AAC7C,MAAMC,0BAA0B;AAEhC,eAAeC;IACb,MAAM,EACJC,+BAA+B,EAC/BC,6BAA6B,EAC7BC,uCAAuC,EACvCC,oCAAoC,EACpCC,wBAAwB,EACxBV,IAAIW,QAAQ,EACZC,gBAAgBC,oBAAoB,EACrC,GAAG,MAAM,MAAM,CAAC;IAEjB,eAAeC,kBACbC,EAAU;QAEV,MAAMC,aAAa,MAAMpB,6BAA6BmB;QACtD,IAAI,CAACC,YAAY,OAAOC;QACxB,OAAOD;IACT;IAEA,eAAeE,0BACbC,KAAqC;QAErC,OAAO,MAAMhB,6BAA6B,IACxCH,KAAKoB,WAAW,CAAC,OAAOC;gBACtB,MAAMC,WAAW5B,sBAAsB,CAAC,OAAO,EAAEyB,MAAMI,OAAO,EAAE,EAAE;oBAACC,UAAU;gBAAQ;gBACrF,MAAMC,OAAO,MAAM5B,4BACjB;oBACE6B,aAAaP,MAAMO,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBT,MAAMU,gBAAgB;oBACzCP;gBACF,GACA;oBAACD;gBAAE;gBAEL,MAAML,aAAa,MAAMjB,4BACvB;oBACE2B,aAAaP,MAAMO,WAAW;oBAC9BC,UAAU;oBACVC,mBAAmBT,MAAMU,gBAAgB;oBACzCJ;oBACAK,aAAaX,MAAMW,WAAW;oBAC9BC,iBAAiB;gBACnB,GACA;oBAACV;gBAAE;gBAGL,MAAMX,yBACJ;oBACEsB,cAAchB,WAAWD,EAAE;oBAC3Bc,kBAAkBV,MAAMU,gBAAgB;oBACxCN,SAASJ,MAAMI,OAAO;oBACtBU,QAAQ;oBACRC,UAAUf,MAAMe,QAAQ;oBACxBC,iBAAiBhB,MAAMgB,eAAe;gBACxC,GACA;oBAACd;gBAAE;gBAGL,OAAOL;YACT;IAEJ;IAEA,OAAO;QACLW,UAAUrB,gCAAgC;YACxC8B,uBAAuB,CAAC,EAACP,gBAAgB,EAAC,GACxCrB,wCAAwCqB;YAC1Cf;YACAI;YACAT;YACA4B,QAAQrC;YACRC;YACAC;YACAN;YACA0C,iCAAiCxC;QACnC;QACAyC,UAAU;YACRvC,IAAIW;YACJC,gBAAgBC;YAChB2B,qBAAqBpC;QACvB;QACAqC,SAAS;YAAClC;SAAgC;IAC5C;AACF;AAEA,OAAO,MAAMmC,uBAAkD;IAC7D3B,IAAI;IACJ4B,SAAShD,OAAOiD,mCAAmC;IACnDC,MAAMxC;AACR,EAAE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { RouteExport } from '@shipfox/node-fastify';
|
|
2
|
+
import type { ModuleDatabase, ModuleWorker } from '@shipfox/node-module';
|
|
3
|
+
import type { IntegrationProvider } from '#core/entities/provider.js';
|
|
4
|
+
/**
|
|
5
|
+
* Everything one integration contributes to the composed integrations module:
|
|
6
|
+
* a registry provider, plus an optional dedicated database, background workers,
|
|
7
|
+
* and one-shot boot-time tasks. Providers that own none of these simply omit them.
|
|
8
|
+
*
|
|
9
|
+
* A startup task is run once after modules are initialized (migrations done). The
|
|
10
|
+
* provider owns its own wiring — core runs each task generically and isolates
|
|
11
|
+
* failures so a task can never gate API boot.
|
|
12
|
+
*/
|
|
13
|
+
export interface IntegrationModuleParts {
|
|
14
|
+
provider: IntegrationProvider;
|
|
15
|
+
database?: ModuleDatabase | undefined;
|
|
16
|
+
e2eRoutes?: RouteExport[] | undefined;
|
|
17
|
+
workers?: ModuleWorker[] | undefined;
|
|
18
|
+
startupTasks?: Array<() => Promise<void>> | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A config-gated integration, registered once in `providerModules`. `load` is
|
|
22
|
+
* called lazily and only when `enabled`, so a disabled provider never imports
|
|
23
|
+
* its (potentially heavy) implementation package.
|
|
24
|
+
*/
|
|
25
|
+
export interface IntegrationProviderModule {
|
|
26
|
+
id: string;
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
load(options?: IntegrationProviderModuleLoadOptions): Promise<IntegrationModuleParts>;
|
|
29
|
+
}
|
|
30
|
+
export interface IntegrationProviderModuleLoadOptions {
|
|
31
|
+
secrets?: IntegrationProviderSecrets | undefined;
|
|
32
|
+
}
|
|
33
|
+
export interface IntegrationProviderSecrets {
|
|
34
|
+
github?: IntegrationProviderScopedSecrets | undefined;
|
|
35
|
+
linear?: IntegrationProviderScopedSecrets | undefined;
|
|
36
|
+
deleteSecrets(params: {
|
|
37
|
+
workspaceId: string;
|
|
38
|
+
namespace: string;
|
|
39
|
+
}): Promise<number>;
|
|
40
|
+
}
|
|
41
|
+
export interface IntegrationProviderScopedSecrets {
|
|
42
|
+
getSecret(params: {
|
|
43
|
+
workspaceId: string;
|
|
44
|
+
namespace: string;
|
|
45
|
+
key: string;
|
|
46
|
+
}): Promise<string | null>;
|
|
47
|
+
setSecrets(params: {
|
|
48
|
+
workspaceId: string;
|
|
49
|
+
namespace: string;
|
|
50
|
+
values: Record<string, string>;
|
|
51
|
+
editedBy?: string | null | undefined;
|
|
52
|
+
}): Promise<void>;
|
|
53
|
+
deleteSecrets(params: {
|
|
54
|
+
workspaceId: string;
|
|
55
|
+
namespace: string;
|
|
56
|
+
}): Promise<number>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAEpE;;;;;;;;GAQG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,SAAS,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACtC,OAAO,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC;IACrC,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACvD;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,OAAO,CAAC,EAAE,oCAAoC,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,oCAAoC;IACnD,OAAO,CAAC,EAAE,0BAA0B,GAAG,SAAS,CAAC;CAClD;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,gCAAgC,GAAG,SAAS,CAAC;IACtD,MAAM,CAAC,EAAE,gCAAgC,GAAG,SAAS,CAAC;IACtD,aAAa,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,gCAAgC;IAC/C,SAAS,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjG,UAAU,CAAC,MAAM,EAAE;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;KACtC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,aAAa,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAClF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/types.ts"],"sourcesContent":["import type {RouteExport} from '@shipfox/node-fastify';\nimport type {ModuleDatabase, ModuleWorker} from '@shipfox/node-module';\nimport type {IntegrationProvider} from '#core/entities/provider.js';\n\n/**\n * Everything one integration contributes to the composed integrations module:\n * a registry provider, plus an optional dedicated database, background workers,\n * and one-shot boot-time tasks. Providers that own none of these simply omit them.\n *\n * A startup task is run once after modules are initialized (migrations done). The\n * provider owns its own wiring — core runs each task generically and isolates\n * failures so a task can never gate API boot.\n */\nexport interface IntegrationModuleParts {\n provider: IntegrationProvider;\n database?: ModuleDatabase | undefined;\n e2eRoutes?: RouteExport[] | undefined;\n workers?: ModuleWorker[] | undefined;\n startupTasks?: Array<() => Promise<void>> | undefined;\n}\n\n/**\n * A config-gated integration, registered once in `providerModules`. `load` is\n * called lazily and only when `enabled`, so a disabled provider never imports\n * its (potentially heavy) implementation package.\n */\nexport interface IntegrationProviderModule {\n id: string;\n enabled: boolean;\n load(options?: IntegrationProviderModuleLoadOptions): Promise<IntegrationModuleParts>;\n}\n\nexport interface IntegrationProviderModuleLoadOptions {\n secrets?: IntegrationProviderSecrets | undefined;\n}\n\nexport interface IntegrationProviderSecrets {\n github?: IntegrationProviderScopedSecrets | undefined;\n linear?: IntegrationProviderScopedSecrets | undefined;\n deleteSecrets(params: {workspaceId: string; namespace: string}): Promise<number>;\n}\n\nexport interface IntegrationProviderScopedSecrets {\n getSecret(params: {workspaceId: string; namespace: string; key: string}): Promise<string | null>;\n setSecrets(params: {\n workspaceId: string;\n namespace: string;\n values: Record<string, string>;\n editedBy?: string | null | undefined;\n }): Promise<void>;\n deleteSecrets(params: {workspaceId: string; namespace: string}): Promise<number>;\n}\n"],"names":[],"mappings":"AA0CA,WASC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/providers/webhook.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AAEnE,eAAO,MAAM,qBAAqB,EAAE,yBAiBnC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { config } from '#config.js';
|
|
2
|
+
import { createIntegrationConnection, deleteIntegrationConnection, getIntegrationConnectionById, listIntegrationConnections, updateIntegrationConnectionLifecycleStatus } from '#db/connections.js';
|
|
3
|
+
import { db } from '#db/db.js';
|
|
4
|
+
import { publishIntegrationEventReceived } from '#db/webhook-deliveries.js';
|
|
5
|
+
export const webhookProviderModule = {
|
|
6
|
+
id: 'webhook',
|
|
7
|
+
enabled: config.INTEGRATIONS_ENABLE_WEBHOOK_PROVIDER,
|
|
8
|
+
load: async ()=>{
|
|
9
|
+
const { createWebhookIntegrationProvider } = await import('@shipfox/api-integration-webhook');
|
|
10
|
+
return {
|
|
11
|
+
provider: createWebhookIntegrationProvider({
|
|
12
|
+
coreDb: db,
|
|
13
|
+
createIntegrationConnection,
|
|
14
|
+
listIntegrationConnections,
|
|
15
|
+
getIntegrationConnectionById,
|
|
16
|
+
updateIntegrationConnectionLifecycleStatus,
|
|
17
|
+
deleteIntegrationConnection,
|
|
18
|
+
publishIntegrationEventReceived
|
|
19
|
+
})
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/providers/webhook.ts"],"sourcesContent":["import {config} from '#config.js';\nimport {\n createIntegrationConnection,\n deleteIntegrationConnection,\n getIntegrationConnectionById,\n listIntegrationConnections,\n updateIntegrationConnectionLifecycleStatus,\n} from '#db/connections.js';\nimport {db} from '#db/db.js';\nimport {publishIntegrationEventReceived} from '#db/webhook-deliveries.js';\nimport type {IntegrationProviderModule} from '#providers/types.js';\n\nexport const webhookProviderModule: IntegrationProviderModule = {\n id: 'webhook',\n enabled: config.INTEGRATIONS_ENABLE_WEBHOOK_PROVIDER,\n load: async () => {\n const {createWebhookIntegrationProvider} = await import('@shipfox/api-integration-webhook');\n return {\n provider: createWebhookIntegrationProvider({\n coreDb: db,\n createIntegrationConnection,\n listIntegrationConnections,\n getIntegrationConnectionById,\n updateIntegrationConnectionLifecycleStatus,\n deleteIntegrationConnection,\n publishIntegrationEventReceived,\n }),\n };\n },\n};\n"],"names":["config","createIntegrationConnection","deleteIntegrationConnection","getIntegrationConnectionById","listIntegrationConnections","updateIntegrationConnectionLifecycleStatus","db","publishIntegrationEventReceived","webhookProviderModule","id","enabled","INTEGRATIONS_ENABLE_WEBHOOK_PROVIDER","load","createWebhookIntegrationProvider","provider","coreDb"],"mappings":"AAAA,SAAQA,MAAM,QAAO,aAAa;AAClC,SACEC,2BAA2B,EAC3BC,2BAA2B,EAC3BC,4BAA4B,EAC5BC,0BAA0B,EAC1BC,0CAA0C,QACrC,qBAAqB;AAC5B,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,+BAA+B,QAAO,4BAA4B;AAG1E,OAAO,MAAMC,wBAAmD;IAC9DC,IAAI;IACJC,SAASV,OAAOW,oCAAoC;IACpDC,MAAM;QACJ,MAAM,EAACC,gCAAgC,EAAC,GAAG,MAAM,MAAM,CAAC;QACxD,OAAO;YACLC,UAAUD,iCAAiC;gBACzCE,QAAQT;gBACRL;gBACAG;gBACAD;gBACAE;gBACAH;gBACAK;YACF;QACF;IACF;AACF,EAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,8BAA8B,EAAC,MAAM,+BAA+B,CAAC;AAE7E,wBAAgB,uCAAuC;;EAItD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/activities/index.ts"],"sourcesContent":["import {pruneWebhookDeliveriesActivity} from './prune-webhook-deliveries.js';\n\nexport function createIntegrationsMaintenanceActivities() {\n return {\n pruneWebhookDeliveriesActivity,\n };\n}\n"],"names":["pruneWebhookDeliveriesActivity","createIntegrationsMaintenanceActivities"],"mappings":"AAAA,SAAQA,8BAA8B,QAAO,gCAAgC;AAE7E,OAAO,SAASC;IACd,OAAO;QACLD;IACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune-webhook-deliveries.d.ts","sourceRoot":"","sources":["../../../src/temporal/activities/prune-webhook-deliveries.ts"],"names":[],"mappings":"AAKA,wBAAsB,8BAA8B,IAAI,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC,CAGjF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pruneWebhookDeliveries } from '#db/webhook-deliveries.js';
|
|
2
|
+
import { WEBHOOK_DELIVERY_RETENTION_DAYS } from '#temporal/constants.js';
|
|
3
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
4
|
+
export async function pruneWebhookDeliveriesActivity() {
|
|
5
|
+
const olderThan = new Date(Date.now() - WEBHOOK_DELIVERY_RETENTION_DAYS * MS_PER_DAY);
|
|
6
|
+
return await pruneWebhookDeliveries({
|
|
7
|
+
olderThan
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=prune-webhook-deliveries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/activities/prune-webhook-deliveries.ts"],"sourcesContent":["import {pruneWebhookDeliveries} from '#db/webhook-deliveries.js';\nimport {WEBHOOK_DELIVERY_RETENTION_DAYS} from '#temporal/constants.js';\n\nconst MS_PER_DAY = 24 * 60 * 60 * 1000;\n\nexport async function pruneWebhookDeliveriesActivity(): Promise<{deleted: number}> {\n const olderThan = new Date(Date.now() - WEBHOOK_DELIVERY_RETENTION_DAYS * MS_PER_DAY);\n return await pruneWebhookDeliveries({olderThan});\n}\n"],"names":["pruneWebhookDeliveries","WEBHOOK_DELIVERY_RETENTION_DAYS","MS_PER_DAY","pruneWebhookDeliveriesActivity","olderThan","Date","now"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,4BAA4B;AACjE,SAAQC,+BAA+B,QAAO,yBAAyB;AAEvE,MAAMC,aAAa,KAAK,KAAK,KAAK;AAElC,OAAO,eAAeC;IACpB,MAAMC,YAAY,IAAIC,KAAKA,KAAKC,GAAG,KAAKL,kCAAkCC;IAC1E,OAAO,MAAMF,uBAAuB;QAACI;IAAS;AAChD"}
|