@shipfox/api-integration-github 11.0.0 → 12.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/core/source-control.d.ts +2 -1
- package/dist/core/source-control.d.ts.map +1 -1
- package/dist/core/source-control.js +56 -1
- package/dist/core/source-control.js.map +1 -1
- package/dist/core/webhook-processor.d.ts +2 -1
- package/dist/core/webhook-processor.d.ts.map +1 -1
- package/dist/core/webhook-processor.js +1 -0
- package/dist/core/webhook-processor.js.map +1 -1
- package/dist/core/webhook.d.ts +3 -2
- package/dist/core/webhook.d.ts.map +1 -1
- package/dist/core/webhook.js +103 -1
- package/dist/core/webhook.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- 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.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/connection-external-url.test.ts +1 -0
- package/src/core/agent-tools.test.ts +1 -0
- package/src/core/source-control.test.ts +80 -0
- package/src/core/source-control.ts +72 -0
- package/src/core/webhook-processor.test.ts +4 -0
- package/src/core/webhook-processor.ts +3 -0
- package/src/core/webhook.test.ts +197 -2
- package/src/core/webhook.ts +150 -0
- package/src/index.test.ts +1 -0
- package/src/index.ts +3 -0
- package/src/presentation/routes/install.test.ts +2 -1
- package/src/presentation/routes/webhooks.test.ts +49 -1
- package/src/presentation/routes/webhooks.ts +2 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n PublishSourcePushFn,\n RecordDeliveryOnlyFn,\n} from '@shipfox/api-integration-spi';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {createGithubApiClient, type GithubApiClient} from '#api/client.js';\nimport type {GithubInstallationTokenProvider} from '#api/installation-token-provider.js';\nimport {deleteGithubInstallationTokenSecret} from '#api/installation-token-provider.js';\nimport {GithubAgentToolsProvider} from '#core/agent-tools.js';\nimport {GithubSourceControlProvider} from '#core/source-control.js';\nimport {createGithubWebhookProcessor} from '#core/webhook-processor.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getGithubInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateGithubE2eRoutesOptions,\n createGithubE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nimport {\n type CreateGithubIntegrationRoutesOptions,\n createGithubIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {createGithubWebhookRoutes} from '#presentation/routes/webhooks.js';\n\nexport type {GithubApiClient} from '#api/client.js';\nexport {\n encodeInstallationTokenEnvelope,\n githubInstallationTokenNamespace,\n} from '#api/installation-token-envelope.js';\nexport {\n createGithubInstallationTokenProvider,\n type GithubInstallationTokenProvider,\n} from '#api/installation-token-provider.js';\nexport {\n type GithubAgentToolCatalogEntry,\n type GithubAgentToolCategory,\n type GithubAgentToolId,\n type GithubAgentToolPermission,\n type GithubAgentToolPermissionAccess,\n type GithubAgentToolRequiredPermission,\n type GithubAgentToolRequiredScope,\n GithubAgentToolsProvider,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport {GithubIntegrationProviderError} from '#core/errors.js';\nexport type {ConnectGithubInstallationInput} from '#core/install.js';\nexport {handleGithubCallback} from '#core/install.js';\nexport {signGithubInstallState, verifyGithubInstallState} from '#core/state.js';\nexport type {HandleGithubEventOutcome} from '#core/webhook.js';\nexport {handleGithubEvent} from '#core/webhook.js';\nexport type {\n CreateGithubWebhookProcessorOptions,\n GithubWebhookProcessor,\n} from '#core/webhook-processor.js';\nexport {createGithubWebhookProcessor} from '#core/webhook-processor.js';\nexport type {GithubInstallation, UpsertGithubInstallationParams} from '#db/installations.js';\nexport {\n getGithubInstallationByConnectionId,\n getGithubInstallationByInstallationId,\n upsertGithubInstallation,\n} from '#db/installations.js';\nexport {type CreateGithubE2eRoutesOptions, closeDb, createGithubE2eRoutes, db, migrationsPath};\n\nexport interface CreateGithubIntegrationProviderOptions\n extends Omit<CreateGithubIntegrationRoutesOptions, 'github'> {\n github?: GithubApiClient | undefined;\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n publishSourcePush: PublishSourcePushFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n getGithubInstallationByConnectionId?: typeof getGithubInstallationByConnectionId | undefined;\n deleteSecrets?:\n | ((params: {workspaceId: string; namespace: string}) => Promise<number>)\n | undefined;\n agentTools?: {tokenProvider: GithubInstallationTokenProvider} | undefined;\n}\n\nexport function createGithubIntegrationProvider(options: CreateGithubIntegrationProviderOptions) {\n const github = options.github ?? createGithubApiClient();\n const getInstallationByConnectionId =\n options.getGithubInstallationByConnectionId ?? getGithubInstallationByConnectionId;\n const deleteSecrets = options.deleteSecrets;\n const deleteInstallationTokenSecret = deleteSecrets\n ? (params: {workspaceId: string; installationId: number}) =>\n deleteGithubInstallationTokenSecret({\n workspaceId: params.workspaceId,\n installationId: params.installationId,\n deleteSecrets,\n })\n : undefined;\n const webhookProcessor = createGithubWebhookProcessor({\n ...options,\n deleteInstallationTokenSecret,\n });\n\n return {\n provider: 'github' as const,\n displayName: 'GitHub',\n adapters: {\n source_control: new GithubSourceControlProvider(github),\n agent_tools: new GithubAgentToolsProvider({\n getInstallationByConnectionId: getInstallationByConnectionId,\n tokenProvider: options.agentTools?.tokenProvider,\n }),\n },\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation) return undefined;\n const installationId = encodeURIComponent(installation.installationId);\n if (installation.accountType === 'Organization') {\n const login = encodeURIComponent(installation.accountLogin);\n return `https://github.com/organizations/${login}/settings/installations/${installationId}`;\n }\n return `https://github.com/settings/installations/${installationId}`;\n },\n routes: [\n createGithubIntegrationRoutes({\n github,\n getExistingGithubConnection: options.getExistingGithubConnection,\n connectGithubInstallation: options.connectGithubInstallation,\n ...(options.requireActiveWorkspaceMembership\n ? {requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership}\n : {}),\n }),\n createGithubWebhookRoutes({\n coreDb: options.coreDb,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n publishSourcePush: options.publishSourcePush,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n deleteInstallationTokenSecret,\n processor: webhookProcessor,\n }),\n ],\n webhookProcessors: [{routeIds: ['github'] as const, processor: webhookProcessor}],\n };\n}\n"],"names":["createGithubApiClient","deleteGithubInstallationTokenSecret","GithubAgentToolsProvider","GithubSourceControlProvider","createGithubWebhookProcessor","closeDb","db","getGithubInstallationByConnectionId","migrationsPath","createGithubE2eRoutes","createGithubIntegrationRoutes","createGithubWebhookRoutes","encodeInstallationTokenEnvelope","githubInstallationTokenNamespace","createGithubInstallationTokenProvider","githubAgentToolCatalog","githubAgentToolSelectionCatalog","GithubIntegrationProviderError","handleGithubCallback","signGithubInstallState","verifyGithubInstallState","handleGithubEvent","getGithubInstallationByInstallationId","upsertGithubInstallation","createGithubIntegrationProvider","options","github","getInstallationByConnectionId","deleteSecrets","deleteInstallationTokenSecret","params","workspaceId","installationId","undefined","webhookProcessor","provider","displayName","adapters","source_control","agent_tools","tokenProvider","agentTools","connectionExternalUrl","connection","installation","id","encodeURIComponent","accountType","login","accountLogin","routes","getExistingGithubConnection","connectGithubInstallation","requireActiveWorkspaceMembership","coreDb","publishIntegrationEventReceived","publishSourcePush","recordDeliveryOnly","getIntegrationConnectionById","processor","webhookProcessors","routeIds"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n PublishSourcePushFn,\n PublishSourceRepositoryUpdatedFn,\n RecordDeliveryOnlyFn,\n} from '@shipfox/api-integration-spi';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {createGithubApiClient, type GithubApiClient} from '#api/client.js';\nimport type {GithubInstallationTokenProvider} from '#api/installation-token-provider.js';\nimport {deleteGithubInstallationTokenSecret} from '#api/installation-token-provider.js';\nimport {GithubAgentToolsProvider} from '#core/agent-tools.js';\nimport {GithubSourceControlProvider} from '#core/source-control.js';\nimport {createGithubWebhookProcessor} from '#core/webhook-processor.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getGithubInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateGithubE2eRoutesOptions,\n createGithubE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nimport {\n type CreateGithubIntegrationRoutesOptions,\n createGithubIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {createGithubWebhookRoutes} from '#presentation/routes/webhooks.js';\n\nexport type {GithubApiClient} from '#api/client.js';\nexport {\n encodeInstallationTokenEnvelope,\n githubInstallationTokenNamespace,\n} from '#api/installation-token-envelope.js';\nexport {\n createGithubInstallationTokenProvider,\n type GithubInstallationTokenProvider,\n} from '#api/installation-token-provider.js';\nexport {\n type GithubAgentToolCatalogEntry,\n type GithubAgentToolCategory,\n type GithubAgentToolId,\n type GithubAgentToolPermission,\n type GithubAgentToolPermissionAccess,\n type GithubAgentToolRequiredPermission,\n type GithubAgentToolRequiredScope,\n GithubAgentToolsProvider,\n githubAgentToolCatalog,\n githubAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport {GithubIntegrationProviderError} from '#core/errors.js';\nexport type {ConnectGithubInstallationInput} from '#core/install.js';\nexport {handleGithubCallback} from '#core/install.js';\nexport {signGithubInstallState, verifyGithubInstallState} from '#core/state.js';\nexport type {HandleGithubEventOutcome} from '#core/webhook.js';\nexport {handleGithubEvent} from '#core/webhook.js';\nexport type {\n CreateGithubWebhookProcessorOptions,\n GithubWebhookProcessor,\n} from '#core/webhook-processor.js';\nexport {createGithubWebhookProcessor} from '#core/webhook-processor.js';\nexport type {GithubInstallation, UpsertGithubInstallationParams} from '#db/installations.js';\nexport {\n getGithubInstallationByConnectionId,\n getGithubInstallationByInstallationId,\n upsertGithubInstallation,\n} from '#db/installations.js';\nexport {type CreateGithubE2eRoutesOptions, closeDb, createGithubE2eRoutes, db, migrationsPath};\n\nexport interface CreateGithubIntegrationProviderOptions\n extends Omit<CreateGithubIntegrationRoutesOptions, 'github'> {\n github?: GithubApiClient | undefined;\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n publishSourceRepositoryUpdated: PublishSourceRepositoryUpdatedFn;\n publishSourcePush: PublishSourcePushFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n getGithubInstallationByConnectionId?: typeof getGithubInstallationByConnectionId | undefined;\n deleteSecrets?:\n | ((params: {workspaceId: string; namespace: string}) => Promise<number>)\n | undefined;\n agentTools?: {tokenProvider: GithubInstallationTokenProvider} | undefined;\n}\n\nexport function createGithubIntegrationProvider(options: CreateGithubIntegrationProviderOptions) {\n const github = options.github ?? createGithubApiClient();\n const getInstallationByConnectionId =\n options.getGithubInstallationByConnectionId ?? getGithubInstallationByConnectionId;\n const deleteSecrets = options.deleteSecrets;\n const deleteInstallationTokenSecret = deleteSecrets\n ? (params: {workspaceId: string; installationId: number}) =>\n deleteGithubInstallationTokenSecret({\n workspaceId: params.workspaceId,\n installationId: params.installationId,\n deleteSecrets,\n })\n : undefined;\n const webhookProcessor = createGithubWebhookProcessor({\n ...options,\n deleteInstallationTokenSecret,\n });\n\n return {\n provider: 'github' as const,\n displayName: 'GitHub',\n adapters: {\n source_control: new GithubSourceControlProvider(github),\n agent_tools: new GithubAgentToolsProvider({\n getInstallationByConnectionId: getInstallationByConnectionId,\n tokenProvider: options.agentTools?.tokenProvider,\n }),\n },\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation) return undefined;\n const installationId = encodeURIComponent(installation.installationId);\n if (installation.accountType === 'Organization') {\n const login = encodeURIComponent(installation.accountLogin);\n return `https://github.com/organizations/${login}/settings/installations/${installationId}`;\n }\n return `https://github.com/settings/installations/${installationId}`;\n },\n routes: [\n createGithubIntegrationRoutes({\n github,\n getExistingGithubConnection: options.getExistingGithubConnection,\n connectGithubInstallation: options.connectGithubInstallation,\n ...(options.requireActiveWorkspaceMembership\n ? {requireActiveWorkspaceMembership: options.requireActiveWorkspaceMembership}\n : {}),\n }),\n createGithubWebhookRoutes({\n coreDb: options.coreDb,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n publishSourceRepositoryUpdated: options.publishSourceRepositoryUpdated,\n publishSourcePush: options.publishSourcePush,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n deleteInstallationTokenSecret,\n processor: webhookProcessor,\n }),\n ],\n webhookProcessors: [{routeIds: ['github'] as const, processor: webhookProcessor}],\n };\n}\n"],"names":["createGithubApiClient","deleteGithubInstallationTokenSecret","GithubAgentToolsProvider","GithubSourceControlProvider","createGithubWebhookProcessor","closeDb","db","getGithubInstallationByConnectionId","migrationsPath","createGithubE2eRoutes","createGithubIntegrationRoutes","createGithubWebhookRoutes","encodeInstallationTokenEnvelope","githubInstallationTokenNamespace","createGithubInstallationTokenProvider","githubAgentToolCatalog","githubAgentToolSelectionCatalog","GithubIntegrationProviderError","handleGithubCallback","signGithubInstallState","verifyGithubInstallState","handleGithubEvent","getGithubInstallationByInstallationId","upsertGithubInstallation","createGithubIntegrationProvider","options","github","getInstallationByConnectionId","deleteSecrets","deleteInstallationTokenSecret","params","workspaceId","installationId","undefined","webhookProcessor","provider","displayName","adapters","source_control","agent_tools","tokenProvider","agentTools","connectionExternalUrl","connection","installation","id","encodeURIComponent","accountType","login","accountLogin","routes","getExistingGithubConnection","connectGithubInstallation","requireActiveWorkspaceMembership","coreDb","publishIntegrationEventReceived","publishSourceRepositoryUpdated","publishSourcePush","recordDeliveryOnly","getIntegrationConnectionById","processor","webhookProcessors","routeIds"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, PublishSourcePushFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-spi';
|
|
1
|
+
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, PublishSourcePushFn, PublishSourceRepositoryUpdatedFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-spi';
|
|
2
2
|
import { type RouteGroup } from '@shipfox/node-fastify';
|
|
3
3
|
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
4
4
|
import { type GithubWebhookProcessor } from '#core/webhook-processor.js';
|
|
5
5
|
export interface CreateGithubWebhookRoutesOptions {
|
|
6
6
|
coreDb: () => NodePgDatabase<Record<string, unknown>>;
|
|
7
7
|
publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;
|
|
8
|
+
publishSourceRepositoryUpdated: PublishSourceRepositoryUpdatedFn;
|
|
8
9
|
publishSourcePush: PublishSourcePushFn;
|
|
9
10
|
recordDeliveryOnly: RecordDeliveryOnlyFn;
|
|
10
11
|
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,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AAMpC,MAAM,WAAW,gCAAgC;IAC/C,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;IAC7D,6BAA6B,CAAC,EAC1B,CAAC,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAC7E,SAAS,CAAC;IACd,SAAS,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,GAAG,UAAU,CAgD/F"}
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,8BAA8B,EAC9B,iCAAiC,EACjC,mBAAmB,EACnB,gCAAgC,EAChC,oBAAoB,EAGrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AAMpC,MAAM,WAAW,gCAAgC;IAC/C,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,8BAA8B,EAAE,gCAAgC,CAAC;IACjE,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;IAC7D,6BAA6B,CAAC,EAC1B,CAAC,CAAC,MAAM,EAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAC7E,SAAS,CAAC;IACd,SAAS,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAChD;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,GAAG,UAAU,CAgD/F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n PublishSourcePushFn,\n RecordDeliveryOnlyFn,\n StoredWebhookRequest,\n WebhookProcessingResult,\n} from '@shipfox/api-integration-spi';\nimport {createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES} from '@shipfox/api-integration-spi';\nimport {\n ClientError,\n defineRoute,\n type RouteGroup,\n rawBodyPlugin,\n WEBHOOK_BODY_LIMIT,\n} from '@shipfox/node-fastify';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {\n createGithubWebhookProcessor,\n type GithubWebhookProcessor,\n} from '#core/webhook-processor.js';\n\nconst SIGNATURE_HEADER = 'x-hub-signature-256';\nconst EVENT_HEADER = 'x-github-event';\nconst DELIVERY_HEADER = 'x-github-delivery';\n\nexport interface CreateGithubWebhookRoutesOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n publishSourcePush: PublishSourcePushFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n deleteInstallationTokenSecret?:\n | ((params: {workspaceId: string; installationId: number}) => Promise<unknown>)\n | undefined;\n processor?: GithubWebhookProcessor | undefined;\n}\n\nexport function createGithubWebhookRoutes(options: CreateGithubWebhookRoutesOptions): RouteGroup {\n const processor = options.processor ?? createGithubWebhookProcessor(options);\n\n const pushRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'GitHub App webhook receiver.',\n options: {bodyLimit: WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const deliveryId = request.headers[DELIVERY_HEADER];\n const signature = request.headers[SIGNATURE_HEADER];\n const event = request.headers[EVENT_HEADER];\n\n if (typeof deliveryId !== 'string' || !deliveryId) {\n reply.code(400);\n return {error: 'missing X-GitHub-Delivery header'};\n }\n if (typeof signature !== 'string' || !signature) {\n reply.code(401);\n return {error: 'missing X-Hub-Signature-256 header'};\n }\n if (typeof event !== 'string' || !event) {\n reply.code(400);\n return {error: 'missing X-GitHub-Event header'};\n }\n\n if (!(request.body instanceof Uint8Array)) {\n reply.code(400);\n return {error: 'expected raw JSON body'};\n }\n const result = await processor.process(\n createGithubStoredWebhookRequest({\n body: request.body,\n headers: request.headers,\n rawQueryString: request.raw.url?.split('?')[1] ?? '',\n }),\n );\n return sendGithubWebhookResponse(reply, result);\n },\n });\n\n return {\n prefix: '/webhooks/integrations/github',\n auth: [],\n plugins: [rawBodyPlugin],\n routes: [pushRoute],\n };\n}\n\nfunction createGithubStoredWebhookRequest(input: {\n body: Uint8Array;\n headers: Record<string, string | string[] | undefined>;\n rawQueryString: string;\n}): StoredWebhookRequest {\n if (input.body.byteLength > WEBHOOK_MAX_RAW_BODY_BYTES) {\n throw new ClientError('Webhook request body is too large', 'body-too-large', {status: 413});\n }\n try {\n return createStoredWebhookRequest({\n requestId: randomUUID(),\n routeId: 'github',\n receivedAt: new Date().toISOString(),\n rawQueryString: input.rawQueryString,\n headers: githubWebhookHeaders(input.headers),\n body: input.body,\n });\n } catch (error) {\n throw new ClientError('Webhook request metadata is invalid', 'invalid-webhook-request', {\n cause: error,\n });\n }\n}\n\nfunction githubWebhookHeaders(headers: Record<string, string | string[] | undefined>) {\n return Object.fromEntries(\n ['content-type', DELIVERY_HEADER, EVENT_HEADER, SIGNATURE_HEADER].flatMap((name) => {\n const value = headers[name];\n return typeof value === 'string' ? [[name, value]] : [];\n }),\n );\n}\n\nfunction sendGithubWebhookResponse(\n reply: {code(statusCode: number): void},\n result: WebhookProcessingResult,\n) {\n if (result.outcome !== 'discarded') {\n reply.code(204);\n return null;\n }\n\n switch (result.reason) {\n case 'invalid_signature':\n reply.code(401);\n return {error: 'invalid signature'};\n case 'malformed_payload':\n reply.code(400);\n return {error: 'malformed JSON'};\n case 'connection_unavailable':\n case 'missing_required_input':\n case 'stale_at_receipt':\n case 'unsupported_event':\n reply.code(204);\n return null;\n }\n}\n"],"names":["randomUUID","createStoredWebhookRequest","WEBHOOK_MAX_RAW_BODY_BYTES","ClientError","defineRoute","rawBodyPlugin","WEBHOOK_BODY_LIMIT","createGithubWebhookProcessor","SIGNATURE_HEADER","EVENT_HEADER","DELIVERY_HEADER","createGithubWebhookRoutes","options","processor","pushRoute","method","path","auth","description","bodyLimit","handler","request","reply","deliveryId","headers","signature","event","code","error","body","Uint8Array","result","process","createGithubStoredWebhookRequest","rawQueryString","raw","url","split","sendGithubWebhookResponse","prefix","plugins","routes","input","byteLength","status","requestId","routeId","receivedAt","Date","toISOString","githubWebhookHeaders","cause","Object","fromEntries","flatMap","name","value","outcome","reason"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAc;
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/webhooks.ts"],"sourcesContent":["import {randomUUID} from 'node:crypto';\nimport type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n PublishSourcePushFn,\n PublishSourceRepositoryUpdatedFn,\n RecordDeliveryOnlyFn,\n StoredWebhookRequest,\n WebhookProcessingResult,\n} from '@shipfox/api-integration-spi';\nimport {createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES} from '@shipfox/api-integration-spi';\nimport {\n ClientError,\n defineRoute,\n type RouteGroup,\n rawBodyPlugin,\n WEBHOOK_BODY_LIMIT,\n} from '@shipfox/node-fastify';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {\n createGithubWebhookProcessor,\n type GithubWebhookProcessor,\n} from '#core/webhook-processor.js';\n\nconst SIGNATURE_HEADER = 'x-hub-signature-256';\nconst EVENT_HEADER = 'x-github-event';\nconst DELIVERY_HEADER = 'x-github-delivery';\n\nexport interface CreateGithubWebhookRoutesOptions {\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n publishSourceRepositoryUpdated: PublishSourceRepositoryUpdatedFn;\n publishSourcePush: PublishSourcePushFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n deleteInstallationTokenSecret?:\n | ((params: {workspaceId: string; installationId: number}) => Promise<unknown>)\n | undefined;\n processor?: GithubWebhookProcessor | undefined;\n}\n\nexport function createGithubWebhookRoutes(options: CreateGithubWebhookRoutesOptions): RouteGroup {\n const processor = options.processor ?? createGithubWebhookProcessor(options);\n\n const pushRoute = defineRoute({\n method: 'POST',\n path: '/',\n auth: [],\n description: 'GitHub App webhook receiver.',\n options: {bodyLimit: WEBHOOK_BODY_LIMIT},\n handler: async (request, reply) => {\n const deliveryId = request.headers[DELIVERY_HEADER];\n const signature = request.headers[SIGNATURE_HEADER];\n const event = request.headers[EVENT_HEADER];\n\n if (typeof deliveryId !== 'string' || !deliveryId) {\n reply.code(400);\n return {error: 'missing X-GitHub-Delivery header'};\n }\n if (typeof signature !== 'string' || !signature) {\n reply.code(401);\n return {error: 'missing X-Hub-Signature-256 header'};\n }\n if (typeof event !== 'string' || !event) {\n reply.code(400);\n return {error: 'missing X-GitHub-Event header'};\n }\n\n if (!(request.body instanceof Uint8Array)) {\n reply.code(400);\n return {error: 'expected raw JSON body'};\n }\n const result = await processor.process(\n createGithubStoredWebhookRequest({\n body: request.body,\n headers: request.headers,\n rawQueryString: request.raw.url?.split('?')[1] ?? '',\n }),\n );\n return sendGithubWebhookResponse(reply, result);\n },\n });\n\n return {\n prefix: '/webhooks/integrations/github',\n auth: [],\n plugins: [rawBodyPlugin],\n routes: [pushRoute],\n };\n}\n\nfunction createGithubStoredWebhookRequest(input: {\n body: Uint8Array;\n headers: Record<string, string | string[] | undefined>;\n rawQueryString: string;\n}): StoredWebhookRequest {\n if (input.body.byteLength > WEBHOOK_MAX_RAW_BODY_BYTES) {\n throw new ClientError('Webhook request body is too large', 'body-too-large', {status: 413});\n }\n try {\n return createStoredWebhookRequest({\n requestId: randomUUID(),\n routeId: 'github',\n receivedAt: new Date().toISOString(),\n rawQueryString: input.rawQueryString,\n headers: githubWebhookHeaders(input.headers),\n body: input.body,\n });\n } catch (error) {\n throw new ClientError('Webhook request metadata is invalid', 'invalid-webhook-request', {\n cause: error,\n });\n }\n}\n\nfunction githubWebhookHeaders(headers: Record<string, string | string[] | undefined>) {\n return Object.fromEntries(\n ['content-type', DELIVERY_HEADER, EVENT_HEADER, SIGNATURE_HEADER].flatMap((name) => {\n const value = headers[name];\n return typeof value === 'string' ? [[name, value]] : [];\n }),\n );\n}\n\nfunction sendGithubWebhookResponse(\n reply: {code(statusCode: number): void},\n result: WebhookProcessingResult,\n) {\n if (result.outcome !== 'discarded') {\n reply.code(204);\n return null;\n }\n\n switch (result.reason) {\n case 'invalid_signature':\n reply.code(401);\n return {error: 'invalid signature'};\n case 'malformed_payload':\n reply.code(400);\n return {error: 'malformed JSON'};\n case 'connection_unavailable':\n case 'missing_required_input':\n case 'stale_at_receipt':\n case 'unsupported_event':\n reply.code(204);\n return null;\n }\n}\n"],"names":["randomUUID","createStoredWebhookRequest","WEBHOOK_MAX_RAW_BODY_BYTES","ClientError","defineRoute","rawBodyPlugin","WEBHOOK_BODY_LIMIT","createGithubWebhookProcessor","SIGNATURE_HEADER","EVENT_HEADER","DELIVERY_HEADER","createGithubWebhookRoutes","options","processor","pushRoute","method","path","auth","description","bodyLimit","handler","request","reply","deliveryId","headers","signature","event","code","error","body","Uint8Array","result","process","createGithubStoredWebhookRequest","rawQueryString","raw","url","split","sendGithubWebhookResponse","prefix","plugins","routes","input","byteLength","status","requestId","routeId","receivedAt","Date","toISOString","githubWebhookHeaders","cause","Object","fromEntries","flatMap","name","value","outcome","reason"],"mappings":"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"}
|