@shipfox/api-integration-slack 4.0.0 → 5.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 +1 -1
- package/CHANGELOG.md +24 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +3 -1
- package/dist/api/client.js.map +1 -1
- package/dist/core/webhook.d.ts +5 -3
- package/dist/core/webhook.d.ts.map +1 -1
- package/dist/core/webhook.js +101 -2
- package/dist/core/webhook.js.map +1 -1
- package/dist/db/db.d.ts +34 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/installations.d.ts +2 -0
- package/dist/db/installations.d.ts.map +1 -1
- package/dist/db/installations.js +4 -2
- package/dist/db/installations.js.map +1 -1
- package/dist/db/schema/installations.d.ts +17 -0
- package/dist/db/schema/installations.d.ts.map +1 -1
- package/dist/db/schema/installations.js +3 -1
- package/dist/db/schema/installations.js.map +1 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/presentation/routes/webhooks.d.ts +2 -1
- package/dist/presentation/routes/webhooks.d.ts.map +1 -1
- package/dist/presentation/routes/webhooks.js +1 -0
- package/dist/presentation/routes/webhooks.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0001_dark_tyrannus.sql +1 -0
- package/drizzle/meta/0001_snapshot.json +139 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +18 -28
- package/src/api/client.test.ts +24 -0
- package/src/api/client.ts +3 -1
- package/src/core/disconnect.test.ts +49 -0
- package/src/core/webhook.test.ts +131 -2
- package/src/core/webhook.ts +143 -6
- package/src/db/installations.test.ts +15 -0
- package/src/db/installations.ts +11 -3
- package/src/db/schema/installations.ts +3 -1
- package/src/index.test.ts +11 -0
- package/src/index.ts +11 -0
- package/src/presentation/routes/webhooks.test.ts +28 -1
- package/src/presentation/routes/webhooks.ts +3 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/turbo.json +9 -0
package/dist/index.d.ts
CHANGED
|
@@ -41,9 +41,30 @@ export interface CreateSlackIntegrationProviderOptions {
|
|
|
41
41
|
tokenStore: Pick<SlackTokenStore, 'getAccessToken'>;
|
|
42
42
|
} | undefined;
|
|
43
43
|
getSlackInstallationByConnectionId?: typeof getSlackInstallationByConnectionId | undefined;
|
|
44
|
+
cleanup?: {
|
|
45
|
+
deleteConnectionRecords?: (connection: {
|
|
46
|
+
id: string;
|
|
47
|
+
}, options: {
|
|
48
|
+
tx: unknown;
|
|
49
|
+
}) => Promise<void>;
|
|
50
|
+
deleteConnectionSecrets?: (connection: {
|
|
51
|
+
id: string;
|
|
52
|
+
workspaceId: string;
|
|
53
|
+
}) => Promise<void>;
|
|
54
|
+
} | undefined;
|
|
44
55
|
routes?: SlackRouteOptions | undefined;
|
|
45
56
|
}
|
|
46
57
|
export declare function createSlackIntegrationProvider(options?: CreateSlackIntegrationProviderOptions): {
|
|
58
|
+
routes: RouteGroup[];
|
|
59
|
+
deleteConnectionRecords?: (connection: {
|
|
60
|
+
id: string;
|
|
61
|
+
}, options: {
|
|
62
|
+
tx: unknown;
|
|
63
|
+
}) => Promise<void>;
|
|
64
|
+
deleteConnectionSecrets?: (connection: {
|
|
65
|
+
id: string;
|
|
66
|
+
workspaceId: string;
|
|
67
|
+
}) => Promise<void>;
|
|
47
68
|
provider: string;
|
|
48
69
|
displayName: string;
|
|
49
70
|
adapters: {
|
|
@@ -54,6 +75,5 @@ export declare function createSlackIntegrationProvider(options?: CreateSlackInte
|
|
|
54
75
|
connectionExternalUrl(connection: {
|
|
55
76
|
id: string;
|
|
56
77
|
}): Promise<string | undefined>;
|
|
57
|
-
routes: RouteGroup[];
|
|
58
78
|
};
|
|
59
79
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -60,6 +60,7 @@ export function createSlackIntegrationProvider(options = {}) {
|
|
|
60
60
|
if (!installation) return undefined;
|
|
61
61
|
return `https://app.slack.com/client/${encodeURIComponent(installation.teamId)}`;
|
|
62
62
|
},
|
|
63
|
+
...options.cleanup,
|
|
63
64
|
routes
|
|
64
65
|
};
|
|
65
66
|
}
|
|
@@ -67,7 +68,7 @@ function hasSlackInstallationRoutesOptions(routes) {
|
|
|
67
68
|
return routes.tokenStore !== undefined && routes.getExistingSlackConnection !== undefined && routes.connectSlackInstallation !== undefined && routes.disconnectSlackInstallation !== undefined;
|
|
68
69
|
}
|
|
69
70
|
function hasSlackWebhookRoutesOptions(routes) {
|
|
70
|
-
return routes.coreDb !== undefined && routes.publishIntegrationEventReceived !== undefined && routes.recordDeliveryOnly !== undefined && routes.getIntegrationConnectionById !== undefined;
|
|
71
|
+
return routes.coreDb !== undefined && routes.claimWebhookDelivery !== undefined && routes.publishIntegrationEventReceived !== undefined && routes.recordDeliveryOnly !== undefined && routes.getIntegrationConnectionById !== undefined;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {SLACK_PROVIDER} from '@shipfox/api-integration-slack-dto';\nimport type {RouteGroup} from '@shipfox/node-fastify';\nimport {createSlackApiClient, type SlackApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {SlackAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {SlackTokenStore} from '#core/tokens.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getSlackInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateSlackIntegrationRoutesOptions,\n createSlackIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateSlackWebhookRoutesOptions,\n createSlackWebhookRoutes,\n} from '#presentation/routes/webhooks.js';\n\ntype SlackInstallationRouteOptions = Omit<\n CreateSlackIntegrationRoutesOptions,\n 'slack' | 'connectionCapabilities'\n>;\ntype SlackRouteOptions = Partial<SlackInstallationRouteOptions> &\n Partial<CreateSlackWebhookRoutesOptions>;\n\nexport type {SlackProvider} from '@shipfox/api-integration-slack-dto';\nexport type {SlackApiClient, SlackAuthorization, SlackWebApiResponse} from '#api/client.js';\nexport {createSlackApiClient} from '#api/client.js';\nexport type {\n SlackAgentToolCatalogEntry,\n SlackAgentToolId,\n SlackAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n SLACK_TOOL_METHODS,\n slackAgentToolCatalog,\n slackAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport type {\n SlackAgentToolsProviderOptions,\n SlackToolCallResult,\n} from '#core/agent-tools-provider.js';\nexport {SlackAgentToolsProvider} from '#core/agent-tools-provider.js';\nexport {\n type DisconnectSlackInstallationParams,\n disconnectSlackInstallation,\n} from '#core/disconnect.js';\nexport {\n SlackAccessTokenUnavailableError,\n type SlackAccessTokenUnavailableReason,\n SlackAuthorizationScopeMismatchError,\n SlackBotTokenMissingError,\n SlackConnectionAlreadyLinkedError,\n SlackConnectionNotFoundError,\n SlackEnterpriseInstallUnsupportedError,\n SlackInstallationAlreadyLinkedError,\n SlackInstallStateActorMismatchError,\n SlackInstallStateError,\n SlackIntegrationProviderError,\n SlackOAuthCallbackError,\n} from '#core/errors.js';\nexport type {ConnectSlackInstallationInput, HandleSlackCallbackParams} from '#core/install.js';\nexport {handleSlackCallback, handleSlackOAuthCallbackError} from '#core/install.js';\nexport {\n assertSlackAuthorizationScopes,\n formatSlackBotScopes,\n SLACK_BOT_SCOPES,\n} from '#core/scopes.js';\nexport type {VerifySlackSignatureParams} from '#core/signature.js';\nexport {verifySlackSignature} from '#core/signature.js';\nexport type {SlackInstallStateClaims} from '#core/state.js';\nexport {signSlackInstallState, verifySlackInstallState} from '#core/state.js';\nexport type {\n CreateSlackTokenStoreParams,\n GetSlackAccessTokenParams,\n SlackConnectionResolverResult,\n SlackSecretsStore,\n SlackTokenStore,\n StoreSlackTokensParams,\n} from '#core/tokens.js';\nexport {createSlackTokenStore, slackSecretsNamespace} from '#core/tokens.js';\nexport type {\n HandleSlackCommandParams,\n HandleSlackEventParams,\n SlackWebhookOutcome,\n} from '#core/webhook.js';\nexport {handleSlackCommand, handleSlackEvent, isSelfAuthoredSlackEvent} from '#core/webhook.js';\nexport type {\n SlackInstallation,\n SlackInstallationStatus,\n UpsertSlackInstallationParams,\n} from '#db/installations.js';\nexport {\n deleteSlackInstallationByConnectionId,\n getSlackInstallationByConnectionId,\n getSlackInstallationByTeamId,\n markSlackInstallationRevoked,\n upsertSlackInstallation,\n} from '#db/installations.js';\nexport {\n type CreateSlackE2eRoutesOptions,\n createSlackE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nexport {\n type CreateSlackWebhookRoutesOptions,\n createSlackWebhookRoutes,\n SLACK_WEBHOOK_BODY_LIMIT,\n SLASH_COMMAND_ACK,\n} from '#presentation/routes/webhooks.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateSlackIntegrationProviderOptions {\n slack?: SlackApiClient | undefined;\n agentTools?: {tokenStore: Pick<SlackTokenStore, 'getAccessToken'>} | undefined;\n getSlackInstallationByConnectionId?: typeof getSlackInstallationByConnectionId | undefined;\n routes?: SlackRouteOptions | undefined;\n}\n\nexport function createSlackIntegrationProvider(\n options: CreateSlackIntegrationProviderOptions = {},\n) {\n const slack = options.slack ?? createSlackApiClient();\n const getInstallationByConnectionId =\n options.getSlackInstallationByConnectionId ?? getSlackInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new SlackAgentToolsProvider({\n slack,\n tokenStore: options.agentTools.tokenStore,\n }),\n }\n : {};\n if (\n options.routes &&\n !hasSlackInstallationRoutesOptions(options.routes) &&\n !hasSlackWebhookRoutesOptions(options.routes)\n ) {\n throw new Error('Slack webhook routes require every core persistence dependency');\n }\n const routes: RouteGroup[] = [];\n if (options.routes && hasSlackInstallationRoutesOptions(options.routes)) {\n const {\n tokenStore,\n getExistingSlackConnection,\n connectSlackInstallation,\n disconnectSlackInstallation,\n } = options.routes;\n routes.push(\n createSlackIntegrationRoutes({\n slack,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n tokenStore,\n getExistingSlackConnection,\n connectSlackInstallation,\n disconnectSlackInstallation,\n }),\n );\n }\n if (options.routes && hasSlackWebhookRoutesOptions(options.routes)) {\n routes.push(...createSlackWebhookRoutes(options.routes));\n }\n\n return {\n provider: SLACK_PROVIDER,\n displayName: 'Slack',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation) return undefined;\n return `https://app.slack.com/client/${encodeURIComponent(installation.teamId)}`;\n },\n routes,\n };\n}\n\nfunction hasSlackInstallationRoutesOptions(\n routes: SlackRouteOptions,\n): routes is SlackInstallationRouteOptions {\n return (\n routes.tokenStore !== undefined &&\n routes.getExistingSlackConnection !== undefined &&\n routes.connectSlackInstallation !== undefined &&\n routes.disconnectSlackInstallation !== undefined\n );\n}\n\nfunction hasSlackWebhookRoutesOptions(\n routes: SlackRouteOptions,\n): routes is CreateSlackWebhookRoutesOptions {\n return (\n routes.coreDb !== undefined &&\n routes.publishIntegrationEventReceived !== undefined &&\n routes.recordDeliveryOnly !== undefined &&\n routes.getIntegrationConnectionById !== undefined\n );\n}\n"],"names":["SLACK_PROVIDER","createSlackApiClient","config","SlackAgentToolsProvider","closeDb","db","getSlackInstallationByConnectionId","migrationsPath","createSlackIntegrationRoutes","createSlackWebhookRoutes","SLACK_TOOL_METHODS","slackAgentToolCatalog","slackAgentToolSelectionCatalog","disconnectSlackInstallation","SlackAccessTokenUnavailableError","SlackAuthorizationScopeMismatchError","SlackBotTokenMissingError","SlackConnectionAlreadyLinkedError","SlackConnectionNotFoundError","SlackEnterpriseInstallUnsupportedError","SlackInstallationAlreadyLinkedError","SlackInstallStateActorMismatchError","SlackInstallStateError","SlackIntegrationProviderError","SlackOAuthCallbackError","handleSlackCallback","handleSlackOAuthCallbackError","assertSlackAuthorizationScopes","formatSlackBotScopes","SLACK_BOT_SCOPES","verifySlackSignature","signSlackInstallState","verifySlackInstallState","createSlackTokenStore","slackSecretsNamespace","handleSlackCommand","handleSlackEvent","isSelfAuthoredSlackEvent","deleteSlackInstallationByConnectionId","getSlackInstallationByTeamId","markSlackInstallationRevoked","upsertSlackInstallation","createSlackE2eRoutes","SLACK_WEBHOOK_BODY_LIMIT","SLASH_COMMAND_ACK","createSlackIntegrationProvider","options","slack","getInstallationByConnectionId","adapters","agentTools","agent_tools","tokenStore","routes","hasSlackInstallationRoutesOptions","hasSlackWebhookRoutesOptions","Error","getExistingSlackConnection","connectSlackInstallation","push","connectionCapabilities","provider","displayName","connectionExternalUrl","connection","installation","id","undefined","encodeURIComponent","teamId","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {SLACK_PROVIDER} from '@shipfox/api-integration-slack-dto';\nimport type {RouteGroup} from '@shipfox/node-fastify';\nimport {createSlackApiClient, type SlackApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {SlackAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {SlackTokenStore} from '#core/tokens.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getSlackInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateSlackIntegrationRoutesOptions,\n createSlackIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateSlackWebhookRoutesOptions,\n createSlackWebhookRoutes,\n} from '#presentation/routes/webhooks.js';\n\ntype SlackInstallationRouteOptions = Omit<\n CreateSlackIntegrationRoutesOptions,\n 'slack' | 'connectionCapabilities'\n>;\ntype SlackRouteOptions = Partial<SlackInstallationRouteOptions> &\n Partial<CreateSlackWebhookRoutesOptions>;\n\nexport type {SlackProvider} from '@shipfox/api-integration-slack-dto';\nexport type {SlackApiClient, SlackAuthorization, SlackWebApiResponse} from '#api/client.js';\nexport {createSlackApiClient} from '#api/client.js';\nexport type {\n SlackAgentToolCatalogEntry,\n SlackAgentToolId,\n SlackAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n SLACK_TOOL_METHODS,\n slackAgentToolCatalog,\n slackAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport type {\n SlackAgentToolsProviderOptions,\n SlackToolCallResult,\n} from '#core/agent-tools-provider.js';\nexport {SlackAgentToolsProvider} from '#core/agent-tools-provider.js';\nexport {\n type DisconnectSlackInstallationParams,\n disconnectSlackInstallation,\n} from '#core/disconnect.js';\nexport {\n SlackAccessTokenUnavailableError,\n type SlackAccessTokenUnavailableReason,\n SlackAuthorizationScopeMismatchError,\n SlackBotTokenMissingError,\n SlackConnectionAlreadyLinkedError,\n SlackConnectionNotFoundError,\n SlackEnterpriseInstallUnsupportedError,\n SlackInstallationAlreadyLinkedError,\n SlackInstallStateActorMismatchError,\n SlackInstallStateError,\n SlackIntegrationProviderError,\n SlackOAuthCallbackError,\n} from '#core/errors.js';\nexport type {ConnectSlackInstallationInput, HandleSlackCallbackParams} from '#core/install.js';\nexport {handleSlackCallback, handleSlackOAuthCallbackError} from '#core/install.js';\nexport {\n assertSlackAuthorizationScopes,\n formatSlackBotScopes,\n SLACK_BOT_SCOPES,\n} from '#core/scopes.js';\nexport type {VerifySlackSignatureParams} from '#core/signature.js';\nexport {verifySlackSignature} from '#core/signature.js';\nexport type {SlackInstallStateClaims} from '#core/state.js';\nexport {signSlackInstallState, verifySlackInstallState} from '#core/state.js';\nexport type {\n CreateSlackTokenStoreParams,\n GetSlackAccessTokenParams,\n SlackConnectionResolverResult,\n SlackSecretsStore,\n SlackTokenStore,\n StoreSlackTokensParams,\n} from '#core/tokens.js';\nexport {createSlackTokenStore, slackSecretsNamespace} from '#core/tokens.js';\nexport type {\n HandleSlackCommandParams,\n HandleSlackEventParams,\n SlackWebhookOutcome,\n} from '#core/webhook.js';\nexport {handleSlackCommand, handleSlackEvent, isSelfAuthoredSlackEvent} from '#core/webhook.js';\nexport type {\n SlackInstallation,\n SlackInstallationStatus,\n UpsertSlackInstallationParams,\n} from '#db/installations.js';\nexport {\n deleteSlackInstallationByConnectionId,\n getSlackInstallationByConnectionId,\n getSlackInstallationByTeamId,\n markSlackInstallationRevoked,\n upsertSlackInstallation,\n} from '#db/installations.js';\nexport {\n type CreateSlackE2eRoutesOptions,\n createSlackE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nexport {\n type CreateSlackWebhookRoutesOptions,\n createSlackWebhookRoutes,\n SLACK_WEBHOOK_BODY_LIMIT,\n SLASH_COMMAND_ACK,\n} from '#presentation/routes/webhooks.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateSlackIntegrationProviderOptions {\n slack?: SlackApiClient | undefined;\n agentTools?: {tokenStore: Pick<SlackTokenStore, 'getAccessToken'>} | undefined;\n getSlackInstallationByConnectionId?: typeof getSlackInstallationByConnectionId | undefined;\n cleanup?:\n | {\n deleteConnectionRecords?: (\n connection: {id: string},\n options: {tx: unknown},\n ) => Promise<void>;\n deleteConnectionSecrets?: (connection: {id: string; workspaceId: string}) => Promise<void>;\n }\n | undefined;\n routes?: SlackRouteOptions | undefined;\n}\n\nexport function createSlackIntegrationProvider(\n options: CreateSlackIntegrationProviderOptions = {},\n) {\n const slack = options.slack ?? createSlackApiClient();\n const getInstallationByConnectionId =\n options.getSlackInstallationByConnectionId ?? getSlackInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new SlackAgentToolsProvider({\n slack,\n tokenStore: options.agentTools.tokenStore,\n }),\n }\n : {};\n if (\n options.routes &&\n !hasSlackInstallationRoutesOptions(options.routes) &&\n !hasSlackWebhookRoutesOptions(options.routes)\n ) {\n throw new Error('Slack webhook routes require every core persistence dependency');\n }\n const routes: RouteGroup[] = [];\n if (options.routes && hasSlackInstallationRoutesOptions(options.routes)) {\n const {\n tokenStore,\n getExistingSlackConnection,\n connectSlackInstallation,\n disconnectSlackInstallation,\n } = options.routes;\n routes.push(\n createSlackIntegrationRoutes({\n slack,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n tokenStore,\n getExistingSlackConnection,\n connectSlackInstallation,\n disconnectSlackInstallation,\n }),\n );\n }\n if (options.routes && hasSlackWebhookRoutesOptions(options.routes)) {\n routes.push(...createSlackWebhookRoutes(options.routes));\n }\n\n return {\n provider: SLACK_PROVIDER,\n displayName: 'Slack',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation) return undefined;\n return `https://app.slack.com/client/${encodeURIComponent(installation.teamId)}`;\n },\n ...options.cleanup,\n routes,\n };\n}\n\nfunction hasSlackInstallationRoutesOptions(\n routes: SlackRouteOptions,\n): routes is SlackInstallationRouteOptions {\n return (\n routes.tokenStore !== undefined &&\n routes.getExistingSlackConnection !== undefined &&\n routes.connectSlackInstallation !== undefined &&\n routes.disconnectSlackInstallation !== undefined\n );\n}\n\nfunction hasSlackWebhookRoutesOptions(\n routes: SlackRouteOptions,\n): routes is CreateSlackWebhookRoutesOptions {\n return (\n routes.coreDb !== undefined &&\n routes.claimWebhookDelivery !== undefined &&\n routes.publishIntegrationEventReceived !== undefined &&\n routes.recordDeliveryOnly !== undefined &&\n routes.getIntegrationConnectionById !== undefined\n );\n}\n"],"names":["SLACK_PROVIDER","createSlackApiClient","config","SlackAgentToolsProvider","closeDb","db","getSlackInstallationByConnectionId","migrationsPath","createSlackIntegrationRoutes","createSlackWebhookRoutes","SLACK_TOOL_METHODS","slackAgentToolCatalog","slackAgentToolSelectionCatalog","disconnectSlackInstallation","SlackAccessTokenUnavailableError","SlackAuthorizationScopeMismatchError","SlackBotTokenMissingError","SlackConnectionAlreadyLinkedError","SlackConnectionNotFoundError","SlackEnterpriseInstallUnsupportedError","SlackInstallationAlreadyLinkedError","SlackInstallStateActorMismatchError","SlackInstallStateError","SlackIntegrationProviderError","SlackOAuthCallbackError","handleSlackCallback","handleSlackOAuthCallbackError","assertSlackAuthorizationScopes","formatSlackBotScopes","SLACK_BOT_SCOPES","verifySlackSignature","signSlackInstallState","verifySlackInstallState","createSlackTokenStore","slackSecretsNamespace","handleSlackCommand","handleSlackEvent","isSelfAuthoredSlackEvent","deleteSlackInstallationByConnectionId","getSlackInstallationByTeamId","markSlackInstallationRevoked","upsertSlackInstallation","createSlackE2eRoutes","SLACK_WEBHOOK_BODY_LIMIT","SLASH_COMMAND_ACK","createSlackIntegrationProvider","options","slack","getInstallationByConnectionId","adapters","agentTools","agent_tools","tokenStore","routes","hasSlackInstallationRoutesOptions","hasSlackWebhookRoutesOptions","Error","getExistingSlackConnection","connectSlackInstallation","push","connectionCapabilities","provider","displayName","connectionExternalUrl","connection","installation","id","undefined","encodeURIComponent","teamId","cleanup","coreDb","claimWebhookDelivery","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-core-dto';
|
|
1
|
+
import type { ClaimWebhookDeliveryFn, GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-core-dto';
|
|
2
2
|
import { type RouteGroup } from '@shipfox/node-fastify';
|
|
3
3
|
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
4
4
|
export declare const SLACK_WEBHOOK_BODY_LIMIT: number;
|
|
@@ -8,6 +8,7 @@ export declare const SLASH_COMMAND_ACK: {
|
|
|
8
8
|
};
|
|
9
9
|
export interface CreateSlackWebhookRoutesOptions {
|
|
10
10
|
coreDb: () => NodePgDatabase<Record<string, unknown>>;
|
|
11
|
+
claimWebhookDelivery: ClaimWebhookDeliveryFn;
|
|
11
12
|
publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;
|
|
12
13
|
recordDeliveryOnly: RecordDeliveryOnlyFn;
|
|
13
14
|
getIntegrationConnectionById: GetIntegrationConnectionByIdFn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,8BAA8B,EAC9B,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EAAmC,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAExF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAK9D,eAAO,MAAM,wBAAwB,QAAc,CAAC;AACpD,eAAO,MAAM,iBAAiB;;;CAAgE,CAAC;AAW/F,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,8BAA8B,EAC9B,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,mCAAmC,CAAC;AAK3C,OAAO,EAAmC,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AAExF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAK9D,eAAO,MAAM,wBAAwB,QAAc,CAAC;AACpD,eAAO,MAAM,iBAAiB;;;CAAgE,CAAC;AAW/F,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,oBAAoB,EAAE,sBAAsB,CAAC;IAC7C,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;CAC9D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,+BAA+B,GAAG,UAAU,EAAE,CAoH/F"}
|
|
@@ -73,6 +73,7 @@ export function createSlackWebhookRoutes(options) {
|
|
|
73
73
|
tx,
|
|
74
74
|
deliveryId: eventRequest.event_id,
|
|
75
75
|
envelope: eventRequest,
|
|
76
|
+
claimWebhookDelivery: options.claimWebhookDelivery,
|
|
76
77
|
publishIntegrationEventReceived: options.publishIntegrationEventReceived,
|
|
77
78
|
recordDeliveryOnly: options.recordDeliveryOnly,
|
|
78
79
|
getIntegrationConnectionById: options.getIntegrationConnectionById
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {Buffer} from 'node:buffer';\nimport type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n RecordDeliveryOnlyFn,\n} from '@shipfox/api-integration-core-dto';\nimport {\n slackEventsRequestSchema,\n slackSlashCommandSchema,\n} from '@shipfox/api-integration-slack-dto';\nimport {createRawBodyPlugin, defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {config} from '#config.js';\nimport {verifySlackSignature} from '#core/signature.js';\nimport {handleSlackCommand, handleSlackEvent} from '#core/webhook.js';\n\nexport const SLACK_WEBHOOK_BODY_LIMIT = 1024 * 1024;\nexport const SLASH_COMMAND_ACK = {response_type: 'ephemeral', text: 'Working on it.'} as const;\n\nconst slackJsonRawBodyPlugin = createRawBodyPlugin({\n contentType: 'application/json',\n bodyLimit: SLACK_WEBHOOK_BODY_LIMIT,\n});\nconst slackFormRawBodyPlugin = createRawBodyPlugin({\n contentType: 'application/x-www-form-urlencoded',\n bodyLimit: SLACK_WEBHOOK_BODY_LIMIT,\n});\n\nexport interface CreateSlackWebhookRoutesOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createSlackWebhookRoutes(options: CreateSlackWebhookRoutesOptions): RouteGroup[] {\n const eventsRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'Slack Events API receiver.',\n options: {bodyLimit: SLACK_WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const rawBody = rawRequestBody(request.body);\n if (rawBody === undefined) {\n reply.code(400);\n return {error: 'expected raw JSON body'};\n }\n if (!hasValidSlackSignature(request.headers, rawBody)) {\n reply.code(401);\n return {error: 'invalid signature'};\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawBody);\n } catch (error) {\n logger().warn(\n {errorName: error instanceof Error ? error.name : 'unknown'},\n 'slack events payload JSON parse failed',\n );\n reply.code(400);\n return {error: 'malformed JSON'};\n }\n\n const parsed = slackEventsRequestSchema.safeParse(parsedJson);\n if (!parsed.success) {\n logger().warn(\n {issues: parsed.error.issues},\n 'slack events envelope failed schema validation',\n );\n reply.code(200);\n return null;\n }\n const eventRequest = parsed.data;\n if (eventRequest.type === 'url_verification') {\n reply.code(200);\n return {challenge: eventRequest.challenge};\n }\n\n await options.coreDb().transaction(async (tx) => {\n await handleSlackEvent({\n tx,\n deliveryId: eventRequest.event_id,\n envelope: eventRequest,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n });\n });\n reply.code(200);\n return null;\n },\n });\n\n const commandsRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'Slack slash-command receiver.',\n options: {bodyLimit: SLACK_WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const rawBody = rawRequestBody(request.body);\n if (rawBody === undefined) {\n reply.code(400);\n return {error: 'expected raw form body'};\n }\n if (!hasValidSlackSignature(request.headers, rawBody)) {\n reply.code(401);\n return {error: 'invalid signature'};\n }\n\n const command = slackSlashCommandSchema.safeParse(\n Object.fromEntries(new URLSearchParams(rawBody)),\n );\n if (!command.success) {\n logger().warn({issues: command.error.issues}, 'slack command failed schema validation');\n reply.code(200);\n return SLASH_COMMAND_ACK;\n }\n\n await options.coreDb().transaction(async (tx) => {\n await handleSlackCommand({\n tx,\n deliveryId: command.data.trigger_id,\n command: command.data,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n });\n });\n reply.code(200);\n return SLASH_COMMAND_ACK;\n },\n });\n\n return [\n {\n prefix: '/webhooks/integrations/slack/events',\n auth: [],\n plugins: [slackJsonRawBodyPlugin],\n routes: [eventsRoute],\n },\n {\n prefix: '/webhooks/integrations/slack/commands',\n auth: [],\n plugins: [slackFormRawBodyPlugin],\n routes: [commandsRoute],\n },\n ];\n}\n\nfunction rawRequestBody(body: unknown): string | undefined {\n return Buffer.isBuffer(body) ? body.toString('utf8') : undefined;\n}\n\nfunction hasValidSlackSignature(\n headers: Record<string, string | string[] | undefined>,\n rawBody: string,\n): boolean {\n const signature = headers['x-slack-signature'];\n const timestamp = headers['x-slack-request-timestamp'];\n return verifySlackSignature({\n signingSecret: config.SLACK_SIGNING_SECRET,\n signature: typeof signature === 'string' ? signature : undefined,\n timestamp: typeof timestamp === 'string' ? timestamp : undefined,\n rawBody,\n });\n}\n"],"names":["Buffer","slackEventsRequestSchema","slackSlashCommandSchema","createRawBodyPlugin","defineRoute","logger","config","verifySlackSignature","handleSlackCommand","handleSlackEvent","SLACK_WEBHOOK_BODY_LIMIT","SLASH_COMMAND_ACK","response_type","text","slackJsonRawBodyPlugin","contentType","bodyLimit","slackFormRawBodyPlugin","createSlackWebhookRoutes","options","eventsRoute","method","path","auth","description","handler","request","reply","rawBody","rawRequestBody","body","undefined","code","error","hasValidSlackSignature","headers","parsedJson","JSON","parse","warn","errorName","Error","name","parsed","safeParse","success","issues","eventRequest","data","type","challenge","coreDb","transaction","tx","deliveryId","event_id","envelope","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","commandsRoute","command","Object","fromEntries","URLSearchParams","trigger_id","prefix","plugins","routes","isBuffer","toString","signature","timestamp","signingSecret","SLACK_SIGNING_SECRET"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {Buffer} from 'node:buffer';\nimport type {\n ClaimWebhookDeliveryFn,\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n RecordDeliveryOnlyFn,\n} from '@shipfox/api-integration-core-dto';\nimport {\n slackEventsRequestSchema,\n slackSlashCommandSchema,\n} from '@shipfox/api-integration-slack-dto';\nimport {createRawBodyPlugin, defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {config} from '#config.js';\nimport {verifySlackSignature} from '#core/signature.js';\nimport {handleSlackCommand, handleSlackEvent} from '#core/webhook.js';\n\nexport const SLACK_WEBHOOK_BODY_LIMIT = 1024 * 1024;\nexport const SLASH_COMMAND_ACK = {response_type: 'ephemeral', text: 'Working on it.'} as const;\n\nconst slackJsonRawBodyPlugin = createRawBodyPlugin({\n contentType: 'application/json',\n bodyLimit: SLACK_WEBHOOK_BODY_LIMIT,\n});\nconst slackFormRawBodyPlugin = createRawBodyPlugin({\n contentType: 'application/x-www-form-urlencoded',\n bodyLimit: SLACK_WEBHOOK_BODY_LIMIT,\n});\n\nexport interface CreateSlackWebhookRoutesOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n claimWebhookDelivery: ClaimWebhookDeliveryFn;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n}\n\nexport function createSlackWebhookRoutes(options: CreateSlackWebhookRoutesOptions): RouteGroup[] {\n const eventsRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'Slack Events API receiver.',\n options: {bodyLimit: SLACK_WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const rawBody = rawRequestBody(request.body);\n if (rawBody === undefined) {\n reply.code(400);\n return {error: 'expected raw JSON body'};\n }\n if (!hasValidSlackSignature(request.headers, rawBody)) {\n reply.code(401);\n return {error: 'invalid signature'};\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawBody);\n } catch (error) {\n logger().warn(\n {errorName: error instanceof Error ? error.name : 'unknown'},\n 'slack events payload JSON parse failed',\n );\n reply.code(400);\n return {error: 'malformed JSON'};\n }\n\n const parsed = slackEventsRequestSchema.safeParse(parsedJson);\n if (!parsed.success) {\n logger().warn(\n {issues: parsed.error.issues},\n 'slack events envelope failed schema validation',\n );\n reply.code(200);\n return null;\n }\n const eventRequest = parsed.data;\n if (eventRequest.type === 'url_verification') {\n reply.code(200);\n return {challenge: eventRequest.challenge};\n }\n\n await options.coreDb().transaction(async (tx) => {\n await handleSlackEvent({\n tx,\n deliveryId: eventRequest.event_id,\n envelope: eventRequest,\n claimWebhookDelivery: options.claimWebhookDelivery,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n });\n });\n reply.code(200);\n return null;\n },\n });\n\n const commandsRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'Slack slash-command receiver.',\n options: {bodyLimit: SLACK_WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const rawBody = rawRequestBody(request.body);\n if (rawBody === undefined) {\n reply.code(400);\n return {error: 'expected raw form body'};\n }\n if (!hasValidSlackSignature(request.headers, rawBody)) {\n reply.code(401);\n return {error: 'invalid signature'};\n }\n\n const command = slackSlashCommandSchema.safeParse(\n Object.fromEntries(new URLSearchParams(rawBody)),\n );\n if (!command.success) {\n logger().warn({issues: command.error.issues}, 'slack command failed schema validation');\n reply.code(200);\n return SLASH_COMMAND_ACK;\n }\n\n await options.coreDb().transaction(async (tx) => {\n await handleSlackCommand({\n tx,\n deliveryId: command.data.trigger_id,\n command: command.data,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n });\n });\n reply.code(200);\n return SLASH_COMMAND_ACK;\n },\n });\n\n return [\n {\n prefix: '/webhooks/integrations/slack/events',\n auth: [],\n plugins: [slackJsonRawBodyPlugin],\n routes: [eventsRoute],\n },\n {\n prefix: '/webhooks/integrations/slack/commands',\n auth: [],\n plugins: [slackFormRawBodyPlugin],\n routes: [commandsRoute],\n },\n ];\n}\n\nfunction rawRequestBody(body: unknown): string | undefined {\n return Buffer.isBuffer(body) ? body.toString('utf8') : undefined;\n}\n\nfunction hasValidSlackSignature(\n headers: Record<string, string | string[] | undefined>,\n rawBody: string,\n): boolean {\n const signature = headers['x-slack-signature'];\n const timestamp = headers['x-slack-request-timestamp'];\n return verifySlackSignature({\n signingSecret: config.SLACK_SIGNING_SECRET,\n signature: typeof signature === 'string' ? signature : undefined,\n timestamp: typeof timestamp === 'string' ? timestamp : undefined,\n rawBody,\n });\n}\n"],"names":["Buffer","slackEventsRequestSchema","slackSlashCommandSchema","createRawBodyPlugin","defineRoute","logger","config","verifySlackSignature","handleSlackCommand","handleSlackEvent","SLACK_WEBHOOK_BODY_LIMIT","SLASH_COMMAND_ACK","response_type","text","slackJsonRawBodyPlugin","contentType","bodyLimit","slackFormRawBodyPlugin","createSlackWebhookRoutes","options","eventsRoute","method","path","auth","description","handler","request","reply","rawBody","rawRequestBody","body","undefined","code","error","hasValidSlackSignature","headers","parsedJson","JSON","parse","warn","errorName","Error","name","parsed","safeParse","success","issues","eventRequest","data","type","challenge","coreDb","transaction","tx","deliveryId","event_id","envelope","claimWebhookDelivery","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","commandsRoute","command","Object","fromEntries","URLSearchParams","trigger_id","prefix","plugins","routes","isBuffer","toString","signature","timestamp","signingSecret","SLACK_SIGNING_SECRET"],"mappings":"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"}
|