@shipfox/api-integration-github 8.0.0 → 9.0.1
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 +37 -0
- package/dist/api/client.js +1 -1
- package/dist/api/client.js.map +1 -1
- package/dist/api/installation-token-envelope.d.ts +1 -1
- package/dist/api/installation-token-envelope.d.ts.map +1 -1
- package/dist/api/installation-token-envelope.js +1 -1
- package/dist/api/installation-token-envelope.js.map +1 -1
- package/dist/api/installation-token-provider.d.ts +1 -1
- package/dist/api/installation-token-provider.d.ts.map +1 -1
- package/dist/api/installation-token-provider.js.map +1 -1
- package/dist/core/actions-logs.d.ts +1 -1
- package/dist/core/actions-logs.d.ts.map +1 -1
- package/dist/core/actions-logs.js +2 -2
- package/dist/core/actions-logs.js.map +1 -1
- package/dist/core/agent-tool-selection.d.ts +1 -1
- package/dist/core/agent-tool-selection.d.ts.map +1 -1
- package/dist/core/agent-tool-selection.js +1 -1
- package/dist/core/agent-tool-selection.js.map +1 -1
- package/dist/core/agent-tools.d.ts +4 -4
- package/dist/core/agent-tools.d.ts.map +1 -1
- package/dist/core/agent-tools.js +2 -2
- package/dist/core/agent-tools.js.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +1 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/github-agent-tool-catalog.d.ts +49 -0
- package/dist/core/github-agent-tool-catalog.d.ts.map +1 -0
- package/dist/core/github-agent-tool-catalog.js +867 -0
- package/dist/core/github-agent-tool-catalog.js.map +1 -0
- package/dist/core/install.d.ts +1 -1
- package/dist/core/install.d.ts.map +1 -1
- package/dist/core/install.js.map +1 -1
- package/dist/core/source-control.d.ts +1 -1
- package/dist/core/source-control.d.ts.map +1 -1
- package/dist/core/source-control.js +1 -1
- package/dist/core/source-control.js.map +1 -1
- package/dist/core/webhook-processor.d.ts +1 -1
- package/dist/core/webhook-processor.d.ts.map +1 -1
- package/dist/core/webhook-processor.js +1 -1
- package/dist/core/webhook-processor.js.map +1 -1
- package/dist/core/webhook.d.ts +1 -1
- package/dist/core/webhook.d.ts.map +1 -1
- package/dist/core/webhook.js +1 -1
- package/dist/core/webhook.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +1 -1
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js.map +1 -1
- package/dist/presentation/dto/integrations.d.ts +8 -7
- package/dist/presentation/dto/integrations.d.ts.map +1 -1
- package/dist/presentation/dto/integrations.js +18 -7
- package/dist/presentation/dto/integrations.js.map +1 -1
- package/dist/presentation/e2eRoutes/create-connection.d.ts +1 -1
- package/dist/presentation/e2eRoutes/create-connection.d.ts.map +1 -1
- package/dist/presentation/e2eRoutes/create-connection.js +1 -1
- package/dist/presentation/e2eRoutes/create-connection.js.map +1 -1
- package/dist/presentation/routes/errors.js +1 -1
- package/dist/presentation/routes/errors.js.map +1 -1
- package/dist/presentation/routes/install.d.ts +1 -1
- package/dist/presentation/routes/install.d.ts.map +1 -1
- package/dist/presentation/routes/install.js.map +1 -1
- package/dist/presentation/routes/webhooks.d.ts +1 -1
- package/dist/presentation/routes/webhooks.d.ts.map +1 -1
- package/dist/presentation/routes/webhooks.js +1 -1
- package/dist/presentation/routes/webhooks.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +17 -14
- package/src/api/client.ts +1 -1
- package/src/api/installation-token-envelope.ts +1 -1
- package/src/api/installation-token-provider.test.ts +1 -1
- package/src/api/installation-token-provider.ts +1 -1
- package/src/core/actions-logs.ts +2 -2
- package/src/core/agent-tool-selection.ts +1 -1
- package/src/core/agent-tools.ts +10 -10
- package/src/core/errors.ts +1 -1
- package/src/core/github-agent-tool-catalog.ts +963 -0
- package/src/core/install.test.ts +1 -1
- package/src/core/install.ts +1 -1
- package/src/core/source-control.ts +1 -1
- package/src/core/webhook-processor.test.ts +1 -1
- package/src/core/webhook-processor.ts +1 -1
- package/src/core/webhook.test.ts +1 -1
- package/src/core/webhook.ts +7 -7
- package/src/index.ts +2 -1
- package/src/metrics/instance.ts +1 -1
- package/src/presentation/dto/integrations.ts +24 -6
- package/src/presentation/e2eRoutes/create-connection.ts +2 -2
- package/src/presentation/e2eRoutes/index.test.ts +1 -1
- package/src/presentation/routes/errors.ts +1 -1
- package/src/presentation/routes/install.test.ts +1 -1
- package/src/presentation/routes/install.ts +1 -1
- package/src/presentation/routes/webhooks.test.ts +1 -1
- package/src/presentation/routes/webhooks.ts +2 -5
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import type {IntegrationProviderErrorReason} from '@shipfox/api-integration-
|
|
1
|
+
{"version":3,"sources":["../../src/metrics/instance.ts"],"sourcesContent":["import type {IntegrationProviderErrorReason} from '@shipfox/api-integration-spi';\nimport {instanceMetrics} from '@shipfox/node-opentelemetry';\nimport type {MintErrorClass} from '#api/installation-token-envelope.js';\n\nconst meter = instanceMetrics.getMeter('github');\n\nexport type GithubInstallationTokenLookupOutcome =\n | 'ram-hit'\n | 'db-hit'\n | 'minted'\n | 'served-stale'\n | 'backoff'\n | 'contended-poll';\n\nconst installationTokenLookupCount = meter.createCounter<{\n outcome: GithubInstallationTokenLookupOutcome;\n}>('github_installation_token_lookup', {\n description: 'GitHub installation token cache lookups by serving outcome',\n});\n\nconst installationTokenMintCount = meter.createCounter<{outcome: 'success' | 'failure'}>(\n 'github_installation_token_mint',\n {description: 'GitHub installation token mint attempts by outcome'},\n);\n\nconst installationTokenMintDuration = meter.createHistogram<Record<string, never>>(\n 'github_installation_token_mint_duration',\n {\n description: 'GitHub installation token mint duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: [10, 50, 100, 250, 500, 1000, 2500, 5000, 10000]},\n },\n);\n\nconst installationTokenLockWaitDuration = meter.createHistogram<Record<string, never>>(\n 'github_installation_token_lock_wait_duration',\n {\n description: 'GitHub installation token advisory lock acquire and hold duration',\n unit: 'ms',\n advice: {explicitBucketBoundaries: [0, 1, 5, 10, 25, 50, 100, 250, 500, 1000, 5000]},\n },\n);\n\nconst installationTokenBackoffCount = meter.createCounter<{\n reason: IntegrationProviderErrorReason;\n class: MintErrorClass;\n}>('github_installation_token_backoff', {\n description: 'GitHub installation token mint backoff activations by reason and class',\n});\n\nfunction recordMetric(record: () => void): void {\n try {\n record();\n } catch {\n // Metrics must not affect GitHub provider outcomes.\n }\n}\n\nexport function recordInstallationTokenLookup(outcome: GithubInstallationTokenLookupOutcome): void {\n recordMetric(() => installationTokenLookupCount.add(1, {outcome}));\n}\n\nexport function recordInstallationTokenMint(params: {\n outcome: 'success' | 'failure';\n durationMs: number;\n}): void {\n recordMetric(() => {\n installationTokenMintCount.add(1, {outcome: params.outcome});\n installationTokenMintDuration.record(params.durationMs);\n });\n}\n\nexport function recordInstallationTokenLockWait(durationMs: number): void {\n recordMetric(() => installationTokenLockWaitDuration.record(durationMs));\n}\n\nexport function recordInstallationTokenBackoff(params: {\n reason: IntegrationProviderErrorReason;\n class: MintErrorClass;\n}): void {\n recordMetric(() => installationTokenBackoffCount.add(1, params));\n}\n"],"names":["instanceMetrics","meter","getMeter","installationTokenLookupCount","createCounter","description","installationTokenMintCount","installationTokenMintDuration","createHistogram","unit","advice","explicitBucketBoundaries","installationTokenLockWaitDuration","installationTokenBackoffCount","recordMetric","record","recordInstallationTokenLookup","outcome","add","recordInstallationTokenMint","params","durationMs","recordInstallationTokenLockWait","recordInstallationTokenBackoff"],"mappings":"AACA,SAAQA,eAAe,QAAO,8BAA8B;AAG5D,MAAMC,QAAQD,gBAAgBE,QAAQ,CAAC;AAUvC,MAAMC,+BAA+BF,MAAMG,aAAa,CAErD,oCAAoC;IACrCC,aAAa;AACf;AAEA,MAAMC,6BAA6BL,MAAMG,aAAa,CACpD,kCACA;IAACC,aAAa;AAAoD;AAGpE,MAAME,gCAAgCN,MAAMO,eAAe,CACzD,2CACA;IACEH,aAAa;IACbI,MAAM;IACNC,QAAQ;QAACC,0BAA0B;YAAC;YAAI;YAAI;YAAK;YAAK;YAAK;YAAM;YAAM;YAAM;SAAM;IAAA;AACrF;AAGF,MAAMC,oCAAoCX,MAAMO,eAAe,CAC7D,gDACA;IACEH,aAAa;IACbI,MAAM;IACNC,QAAQ;QAACC,0BAA0B;YAAC;YAAG;YAAG;YAAG;YAAI;YAAI;YAAI;YAAK;YAAK;YAAK;YAAM;SAAK;IAAA;AACrF;AAGF,MAAME,gCAAgCZ,MAAMG,aAAa,CAGtD,qCAAqC;IACtCC,aAAa;AACf;AAEA,SAASS,aAAaC,MAAkB;IACtC,IAAI;QACFA;IACF,EAAE,OAAM;IACN,oDAAoD;IACtD;AACF;AAEA,OAAO,SAASC,8BAA8BC,OAA6C;IACzFH,aAAa,IAAMX,6BAA6Be,GAAG,CAAC,GAAG;YAACD;QAAO;AACjE;AAEA,OAAO,SAASE,4BAA4BC,MAG3C;IACCN,aAAa;QACXR,2BAA2BY,GAAG,CAAC,GAAG;YAACD,SAASG,OAAOH,OAAO;QAAA;QAC1DV,8BAA8BQ,MAAM,CAACK,OAAOC,UAAU;IACxD;AACF;AAEA,OAAO,SAASC,gCAAgCD,UAAkB;IAChEP,aAAa,IAAMF,kCAAkCG,MAAM,CAACM;AAC9D;AAEA,OAAO,SAASE,+BAA+BH,MAG9C;IACCN,aAAa,IAAMD,8BAA8BK,GAAG,CAAC,GAAGE;AAC1D"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function toIntegrationConnectionDto(connection: IntegrationConnection<'github'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
external_url?: string;
|
|
1
|
+
import type { IntegrationCapability, IntegrationConnection } from '@shipfox/api-integration-spi';
|
|
2
|
+
export declare function toIntegrationConnectionDto(connection: IntegrationConnection<'github'>, options?: {
|
|
3
|
+
capabilities?: IntegrationCapability[];
|
|
4
|
+
}): {
|
|
6
5
|
id: string;
|
|
7
6
|
workspace_id: string;
|
|
8
7
|
provider: string;
|
|
9
8
|
external_account_id: string;
|
|
10
9
|
slug: string;
|
|
11
10
|
display_name: string;
|
|
12
|
-
lifecycle_status: import("@shipfox/api-integration-
|
|
13
|
-
capabilities:
|
|
11
|
+
lifecycle_status: import("@shipfox/api-integration-spi").IntegrationConnectionLifecycleStatus;
|
|
12
|
+
capabilities: IntegrationCapability[];
|
|
13
|
+
created_at: string;
|
|
14
|
+
updated_at: string;
|
|
14
15
|
};
|
|
15
16
|
//# sourceMappingURL=integrations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,qBAAqB,EAAE,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AAE/F,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,qBAAqB,CAAC,QAAQ,CAAC,EAC3C,OAAO,GAAE;IAAC,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAA;CAAM;;;;;;;;;;;EAGvD"}
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
export function toIntegrationConnectionDto(connection, options = {}) {
|
|
2
|
+
return mapIntegrationConnection(connection, options.capabilities ?? [
|
|
3
|
+
'source_control'
|
|
4
|
+
]);
|
|
5
|
+
}
|
|
6
|
+
function mapIntegrationConnection(connection, capabilities) {
|
|
7
|
+
return {
|
|
8
|
+
id: connection.id,
|
|
9
|
+
workspace_id: connection.workspaceId,
|
|
10
|
+
provider: connection.provider,
|
|
11
|
+
external_account_id: connection.externalAccountId,
|
|
12
|
+
slug: connection.slug,
|
|
13
|
+
display_name: connection.displayName,
|
|
14
|
+
lifecycle_status: connection.lifecycleStatus,
|
|
15
|
+
capabilities,
|
|
16
|
+
created_at: connection.createdAt.toISOString(),
|
|
17
|
+
updated_at: connection.updatedAt.toISOString()
|
|
18
|
+
};
|
|
8
19
|
}
|
|
9
20
|
|
|
10
21
|
//# sourceMappingURL=integrations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/dto/integrations.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/dto/integrations.ts"],"sourcesContent":["import type {IntegrationCapability, IntegrationConnection} from '@shipfox/api-integration-spi';\n\nexport function toIntegrationConnectionDto(\n connection: IntegrationConnection<'github'>,\n options: {capabilities?: IntegrationCapability[]} = {},\n) {\n return mapIntegrationConnection(connection, options.capabilities ?? ['source_control']);\n}\n\nfunction mapIntegrationConnection(\n connection: IntegrationConnection,\n capabilities: IntegrationCapability[],\n) {\n return {\n id: connection.id,\n workspace_id: connection.workspaceId,\n provider: connection.provider,\n external_account_id: connection.externalAccountId,\n slug: connection.slug,\n display_name: connection.displayName,\n lifecycle_status: connection.lifecycleStatus,\n capabilities,\n created_at: connection.createdAt.toISOString(),\n updated_at: connection.updatedAt.toISOString(),\n };\n}\n"],"names":["toIntegrationConnectionDto","connection","options","mapIntegrationConnection","capabilities","id","workspace_id","workspaceId","provider","external_account_id","externalAccountId","slug","display_name","displayName","lifecycle_status","lifecycleStatus","created_at","createdAt","toISOString","updated_at","updatedAt"],"mappings":"AAEA,OAAO,SAASA,2BACdC,UAA2C,EAC3CC,UAAoD,CAAC,CAAC;IAEtD,OAAOC,yBAAyBF,YAAYC,QAAQE,YAAY,IAAI;QAAC;KAAiB;AACxF;AAEA,SAASD,yBACPF,UAAiC,EACjCG,YAAqC;IAErC,OAAO;QACLC,IAAIJ,WAAWI,EAAE;QACjBC,cAAcL,WAAWM,WAAW;QACpCC,UAAUP,WAAWO,QAAQ;QAC7BC,qBAAqBR,WAAWS,iBAAiB;QACjDC,MAAMV,WAAWU,IAAI;QACrBC,cAAcX,WAAWY,WAAW;QACpCC,kBAAkBb,WAAWc,eAAe;QAC5CX;QACAY,YAAYf,WAAWgB,SAAS,CAACC,WAAW;QAC5CC,YAAYlB,WAAWmB,SAAS,CAACF,WAAW;IAC9C;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IntegrationCapability, IntegrationConnection } from '@shipfox/api-integration-
|
|
1
|
+
import type { IntegrationCapability, IntegrationConnection } from '@shipfox/api-integration-spi';
|
|
2
2
|
import type { ConnectGithubInstallationInput } from '#core/install.js';
|
|
3
3
|
export interface CreateE2eGithubConnectionRouteOptions {
|
|
4
4
|
getExistingGithubConnection: (input: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-connection.d.ts","sourceRoot":"","sources":["../../../src/presentation/e2eRoutes/create-connection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create-connection.d.ts","sourceRoot":"","sources":["../../../src/presentation/e2eRoutes/create-connection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,qBAAqB,EAAE,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AAE/F,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,kBAAkB,CAAC;AAGrE,MAAM,WAAW,qCAAqC;IACpD,2BAA2B,EAAE,CAAC,KAAK,EAAE;QACnC,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CACzB,KAAK,EAAE,8BAA8B,KAClC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;CACjD;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,qCAAqC,mDAkD5F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { toIntegrationConnectionDto } from '@shipfox/api-integration-core-dto';
|
|
2
1
|
import { createE2eGithubConnectionBodySchema, createE2eGithubConnectionResponseSchema } from '@shipfox/api-integration-github-dto';
|
|
3
2
|
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
3
|
+
import { toIntegrationConnectionDto } from '#presentation/dto/integrations.js';
|
|
4
4
|
export function createE2eGithubConnectionRoute(options) {
|
|
5
5
|
return defineRoute({
|
|
6
6
|
method: 'POST',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/e2eRoutes/create-connection.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/e2eRoutes/create-connection.ts"],"sourcesContent":["import {\n createE2eGithubConnectionBodySchema,\n createE2eGithubConnectionResponseSchema,\n} from '@shipfox/api-integration-github-dto';\nimport type {IntegrationCapability, IntegrationConnection} from '@shipfox/api-integration-spi';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport type {ConnectGithubInstallationInput} from '#core/install.js';\nimport {toIntegrationConnectionDto} from '#presentation/dto/integrations.js';\n\nexport interface CreateE2eGithubConnectionRouteOptions {\n getExistingGithubConnection: (input: {\n installationId: string;\n }) => Promise<IntegrationConnection<'github'> | undefined>;\n connectGithubInstallation: (\n input: ConnectGithubInstallationInput,\n ) => Promise<IntegrationConnection<'github'>>;\n connectionCapabilities: IntegrationCapability[];\n}\n\nexport function createE2eGithubConnectionRoute(options: CreateE2eGithubConnectionRouteOptions) {\n return defineRoute({\n method: 'POST',\n path: '/github-connections',\n description: 'Create a synthetic GitHub connection for E2E tests.',\n schema: {\n body: createE2eGithubConnectionBodySchema,\n response: {201: createE2eGithubConnectionResponseSchema},\n },\n handler: async (request, reply) => {\n const body = request.body;\n const installationId = String(body.installation_id);\n const existing = await options.getExistingGithubConnection({installationId});\n if (existing && existing.workspaceId !== body.workspace_id) {\n throw new ClientError(\n 'GitHub installation is already connected to another workspace',\n 'github-connection-workspace-mismatch',\n {status: 409},\n );\n }\n\n const connection =\n existing ??\n (await options.connectGithubInstallation({\n workspaceId: body.workspace_id,\n installationId,\n displayName: body.display_name,\n installerUserId: body.installer_user_id,\n installation: {\n installationId,\n accountLogin: body.account_login,\n accountType: 'Organization',\n repositorySelection: 'all',\n suspendedAt: null,\n deletedAt: null,\n latestEvent: {\n id: body.installation_id,\n account: {login: body.account_login, type: 'Organization'},\n repository_selection: 'all',\n },\n installerUserId: body.installer_user_id,\n },\n }));\n\n reply.code(201);\n return toIntegrationConnectionDto(connection, {\n capabilities: options.connectionCapabilities,\n });\n },\n });\n}\n"],"names":["createE2eGithubConnectionBodySchema","createE2eGithubConnectionResponseSchema","ClientError","defineRoute","toIntegrationConnectionDto","createE2eGithubConnectionRoute","options","method","path","description","schema","body","response","handler","request","reply","installationId","String","installation_id","existing","getExistingGithubConnection","workspaceId","workspace_id","status","connection","connectGithubInstallation","displayName","display_name","installerUserId","installer_user_id","installation","accountLogin","account_login","accountType","repositorySelection","suspendedAt","deletedAt","latestEvent","id","account","login","type","repository_selection","code","capabilities","connectionCapabilities"],"mappings":"AAAA,SACEA,mCAAmC,EACnCC,uCAAuC,QAClC,sCAAsC;AAE7C,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAE/D,SAAQC,0BAA0B,QAAO,oCAAoC;AAY7E,OAAO,SAASC,+BAA+BC,OAA8C;IAC3F,OAAOH,YAAY;QACjBI,QAAQ;QACRC,MAAM;QACNC,aAAa;QACbC,QAAQ;YACNC,MAAMX;YACNY,UAAU;gBAAC,KAAKX;YAAuC;QACzD;QACAY,SAAS,OAAOC,SAASC;YACvB,MAAMJ,OAAOG,QAAQH,IAAI;YACzB,MAAMK,iBAAiBC,OAAON,KAAKO,eAAe;YAClD,MAAMC,WAAW,MAAMb,QAAQc,2BAA2B,CAAC;gBAACJ;YAAc;YAC1E,IAAIG,YAAYA,SAASE,WAAW,KAAKV,KAAKW,YAAY,EAAE;gBAC1D,MAAM,IAAIpB,YACR,iEACA,wCACA;oBAACqB,QAAQ;gBAAG;YAEhB;YAEA,MAAMC,aACJL,YACC,MAAMb,QAAQmB,yBAAyB,CAAC;gBACvCJ,aAAaV,KAAKW,YAAY;gBAC9BN;gBACAU,aAAaf,KAAKgB,YAAY;gBAC9BC,iBAAiBjB,KAAKkB,iBAAiB;gBACvCC,cAAc;oBACZd;oBACAe,cAAcpB,KAAKqB,aAAa;oBAChCC,aAAa;oBACbC,qBAAqB;oBACrBC,aAAa;oBACbC,WAAW;oBACXC,aAAa;wBACXC,IAAI3B,KAAKO,eAAe;wBACxBqB,SAAS;4BAACC,OAAO7B,KAAKqB,aAAa;4BAAES,MAAM;wBAAc;wBACzDC,sBAAsB;oBACxB;oBACAd,iBAAiBjB,KAAKkB,iBAAiB;gBACzC;YACF;YAEFd,MAAM4B,IAAI,CAAC;YACX,OAAOvC,2BAA2BoB,YAAY;gBAC5CoB,cAActC,QAAQuC,sBAAsB;YAC9C;QACF;IACF;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConnectionSlugConflictError } from '@shipfox/api-integration-
|
|
1
|
+
import { ConnectionSlugConflictError } from '@shipfox/api-integration-spi';
|
|
2
2
|
import { ClientError } from '@shipfox/node-fastify';
|
|
3
3
|
import { GithubInstallationAlreadyLinkedError, GithubInstallationNotAuthorizedError, GithubInstallStateActorMismatchError, GithubInstallStateError, GithubIntegrationProviderError } from '#core/errors.js';
|
|
4
4
|
function providerStatus(reason) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {\n ConnectionSlugConflictError,\n type IntegrationProviderErrorReason,\n} from '@shipfox/api-integration-
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {\n ConnectionSlugConflictError,\n type IntegrationProviderErrorReason,\n} from '@shipfox/api-integration-spi';\nimport {ClientError} from '@shipfox/node-fastify';\nimport {\n GithubInstallationAlreadyLinkedError,\n GithubInstallationNotAuthorizedError,\n GithubInstallStateActorMismatchError,\n GithubInstallStateError,\n GithubIntegrationProviderError,\n} from '#core/errors.js';\n\nfunction providerStatus(reason: IntegrationProviderErrorReason): number {\n if (reason === 'rate-limited') return 429;\n if (reason === 'timeout' || reason === 'provider-unavailable') return 503;\n return 422;\n}\n\nexport function githubRouteErrorHandler(error: unknown): never {\n if (error instanceof GithubInstallStateError) {\n throw new ClientError(error.message, 'invalid-github-install-state', {status: 400});\n }\n if (error instanceof GithubInstallStateActorMismatchError) {\n throw new ClientError(error.message, 'github-install-state-actor-mismatch', {status: 403});\n }\n if (error instanceof GithubInstallationNotAuthorizedError) {\n throw new ClientError(error.message, 'github-installation-not-authorized', {status: 403});\n }\n if (error instanceof GithubInstallationAlreadyLinkedError) {\n throw new ClientError(error.message, 'github-installation-already-linked', {status: 409});\n }\n if (error instanceof ConnectionSlugConflictError) {\n throw new ClientError(error.message, 'slug-conflict', {status: 409});\n }\n if (error instanceof GithubIntegrationProviderError) {\n throw new ClientError(error.message, error.reason, {\n details: {retry_after_seconds: error.retryAfterSeconds},\n status: providerStatus(error.reason),\n });\n }\n throw error;\n}\n"],"names":["ConnectionSlugConflictError","ClientError","GithubInstallationAlreadyLinkedError","GithubInstallationNotAuthorizedError","GithubInstallStateActorMismatchError","GithubInstallStateError","GithubIntegrationProviderError","providerStatus","reason","githubRouteErrorHandler","error","message","status","details","retry_after_seconds","retryAfterSeconds"],"mappings":"AAAA,SACEA,2BAA2B,QAEtB,+BAA+B;AACtC,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SACEC,oCAAoC,EACpCC,oCAAoC,EACpCC,oCAAoC,EACpCC,uBAAuB,EACvBC,8BAA8B,QACzB,kBAAkB;AAEzB,SAASC,eAAeC,MAAsC;IAC5D,IAAIA,WAAW,gBAAgB,OAAO;IACtC,IAAIA,WAAW,aAAaA,WAAW,wBAAwB,OAAO;IACtE,OAAO;AACT;AAEA,OAAO,SAASC,wBAAwBC,KAAc;IACpD,IAAIA,iBAAiBL,yBAAyB;QAC5C,MAAM,IAAIJ,YAAYS,MAAMC,OAAO,EAAE,gCAAgC;YAACC,QAAQ;QAAG;IACnF;IACA,IAAIF,iBAAiBN,sCAAsC;QACzD,MAAM,IAAIH,YAAYS,MAAMC,OAAO,EAAE,uCAAuC;YAACC,QAAQ;QAAG;IAC1F;IACA,IAAIF,iBAAiBP,sCAAsC;QACzD,MAAM,IAAIF,YAAYS,MAAMC,OAAO,EAAE,sCAAsC;YAACC,QAAQ;QAAG;IACzF;IACA,IAAIF,iBAAiBR,sCAAsC;QACzD,MAAM,IAAID,YAAYS,MAAMC,OAAO,EAAE,sCAAsC;YAACC,QAAQ;QAAG;IACzF;IACA,IAAIF,iBAAiBV,6BAA6B;QAChD,MAAM,IAAIC,YAAYS,MAAMC,OAAO,EAAE,iBAAiB;YAACC,QAAQ;QAAG;IACpE;IACA,IAAIF,iBAAiBJ,gCAAgC;QACnD,MAAM,IAAIL,YAAYS,MAAMC,OAAO,EAAED,MAAMF,MAAM,EAAE;YACjDK,SAAS;gBAACC,qBAAqBJ,MAAMK,iBAAiB;YAAA;YACtDH,QAAQL,eAAeG,MAAMF,MAAM;QACrC;IACF;IACA,MAAME;AACR"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IntegrationConnection } from '@shipfox/api-integration-
|
|
1
|
+
import type { IntegrationConnection } from '@shipfox/api-integration-spi';
|
|
2
2
|
import { type RouteGroup } from '@shipfox/node-fastify';
|
|
3
3
|
import type { GithubApiClient } from '#api/client.js';
|
|
4
4
|
import { type ConnectGithubInstallationInput } from '#core/install.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/install.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAc,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAC,KAAK,8BAA8B,EAAuB,MAAM,kBAAkB,CAAC;AAK3F,MAAM,WAAW,oCAAoC;IACnD,MAAM,EAAE,eAAe,CAAC;IACxB,2BAA2B,EAAE,CAAC,KAAK,EAAE;QACnC,cAAc,EAAE,MAAM,CAAC;KACxB,KAAK,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;IAC3D,yBAAyB,EAAE,CACzB,KAAK,EAAE,8BAA8B,KAClC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,gCAAgC,CAAC,EAAE,CAAC,KAAK,EAAE;QACzC,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,aAAa,CAAC,OAAO,2BAA2B,EAAE,qBAAqB,CAAC,CAAC;KACvF,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,MAAM,EACN,2BAA2B,EAC3B,yBAAyB,EACzB,gCAAgC,GACjC,EAAE,oCAAoC,GAAG,UAAU,CA8DnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/routes/install.ts"],"sourcesContent":["import {AUTH_USER, requireUserContext, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/install.ts"],"sourcesContent":["import {AUTH_USER, requireUserContext, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport {\n createGithubInstallBodySchema,\n createGithubInstallResponseSchema,\n githubCallbackQuerySchema,\n githubCallbackResponseSchema,\n} from '@shipfox/api-integration-github-dto';\nimport type {IntegrationConnection} from '@shipfox/api-integration-spi';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport type {GithubApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {type ConnectGithubInstallationInput, handleGithubCallback} from '#core/install.js';\nimport {signGithubInstallState} from '#core/state.js';\nimport {toIntegrationConnectionDto} from '#presentation/dto/integrations.js';\nimport {githubRouteErrorHandler} from './errors.js';\n\nexport interface CreateGithubIntegrationRoutesOptions {\n github: GithubApiClient;\n getExistingGithubConnection: (input: {\n installationId: string;\n }) => Promise<IntegrationConnection<'github'> | undefined>;\n connectGithubInstallation: (\n input: ConnectGithubInstallationInput,\n ) => Promise<IntegrationConnection<'github'>>;\n requireActiveWorkspaceMembership?: (input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<import('@shipfox/api-auth-context').UserContextMembership>;\n }) => Promise<unknown>;\n}\n\nexport function createGithubIntegrationRoutes({\n github,\n getExistingGithubConnection,\n connectGithubInstallation,\n requireActiveWorkspaceMembership,\n}: CreateGithubIntegrationRoutesOptions): RouteGroup {\n const createInstallRoute = defineRoute({\n method: 'POST',\n path: '/install',\n auth: AUTH_USER,\n description: 'Create a GitHub App installation URL for a workspace.',\n schema: {\n body: createGithubInstallBodySchema,\n response: {\n 200: createGithubInstallResponseSchema,\n },\n },\n handler: (request) => {\n const {workspace_id: workspaceId} = request.body;\n const actor = requireUserContext(request);\n\n requireWorkspaceAccess({request, workspaceId});\n const state = signGithubInstallState({workspaceId, userId: actor.userId});\n const installUrl = new URL(\n `https://github.com/apps/${config.GITHUB_APP_SLUG}/installations/new`,\n );\n installUrl.searchParams.set('state', state);\n\n return {install_url: installUrl.toString()};\n },\n });\n\n const callbackApiRoute = defineRoute({\n method: 'GET',\n path: '/callback/api',\n auth: AUTH_USER,\n description: 'Handle the GitHub App installation callback.',\n schema: {\n querystring: githubCallbackQuerySchema,\n response: {\n 200: githubCallbackResponseSchema,\n },\n },\n errorHandler: githubRouteErrorHandler,\n handler: async (request) => {\n const actor = requireUserContext(request);\n const connection = await handleGithubCallback({\n github,\n code: request.query.code,\n installationId: request.query.installation_id,\n state: request.query.state,\n sessionUserId: actor.userId,\n sessionMemberships: actor.memberships,\n requireWorkspaceMembership:\n requireActiveWorkspaceMembership ?? unavailableWorkspaceMembershipCheck,\n getExistingGithubConnection,\n connectGithubInstallation,\n });\n\n return toIntegrationConnectionDto(connection);\n },\n });\n\n return {\n prefix: '/integrations/github',\n routes: [createInstallRoute, callbackApiRoute],\n };\n}\n\nfunction unavailableWorkspaceMembershipCheck(_input: {\n workspaceId: string;\n userId: string;\n memberships: ReadonlyArray<import('@shipfox/api-auth-context').UserContextMembership>;\n}): Promise<never> {\n return Promise.reject(new Error('Workspaces inter-module client is not configured'));\n}\n"],"names":["AUTH_USER","requireUserContext","requireWorkspaceAccess","createGithubInstallBodySchema","createGithubInstallResponseSchema","githubCallbackQuerySchema","githubCallbackResponseSchema","defineRoute","config","handleGithubCallback","signGithubInstallState","toIntegrationConnectionDto","githubRouteErrorHandler","createGithubIntegrationRoutes","github","getExistingGithubConnection","connectGithubInstallation","requireActiveWorkspaceMembership","createInstallRoute","method","path","auth","description","schema","body","response","handler","request","workspace_id","workspaceId","actor","state","userId","installUrl","URL","GITHUB_APP_SLUG","searchParams","set","install_url","toString","callbackApiRoute","querystring","errorHandler","connection","code","query","installationId","installation_id","sessionUserId","sessionMemberships","memberships","requireWorkspaceMembership","unavailableWorkspaceMembershipCheck","prefix","routes","_input","Promise","reject","Error"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,kBAAkB,EAAEC,sBAAsB,QAAO,4BAA4B;AAChG,SACEC,6BAA6B,EAC7BC,iCAAiC,EACjCC,yBAAyB,EACzBC,4BAA4B,QACvB,sCAAsC;AAE7C,SAAQC,WAAW,QAAwB,wBAAwB;AAEnE,SAAQC,MAAM,QAAO,aAAa;AAClC,SAA6CC,oBAAoB,QAAO,mBAAmB;AAC3F,SAAQC,sBAAsB,QAAO,iBAAiB;AACtD,SAAQC,0BAA0B,QAAO,oCAAoC;AAC7E,SAAQC,uBAAuB,QAAO,cAAc;AAiBpD,OAAO,SAASC,8BAA8B,EAC5CC,MAAM,EACNC,2BAA2B,EAC3BC,yBAAyB,EACzBC,gCAAgC,EACK;IACrC,MAAMC,qBAAqBX,YAAY;QACrCY,QAAQ;QACRC,MAAM;QACNC,MAAMrB;QACNsB,aAAa;QACbC,QAAQ;YACNC,MAAMrB;YACNsB,UAAU;gBACR,KAAKrB;YACP;QACF;QACAsB,SAAS,CAACC;YACR,MAAM,EAACC,cAAcC,WAAW,EAAC,GAAGF,QAAQH,IAAI;YAChD,MAAMM,QAAQ7B,mBAAmB0B;YAEjCzB,uBAAuB;gBAACyB;gBAASE;YAAW;YAC5C,MAAME,QAAQrB,uBAAuB;gBAACmB;gBAAaG,QAAQF,MAAME,MAAM;YAAA;YACvE,MAAMC,aAAa,IAAIC,IACrB,CAAC,wBAAwB,EAAE1B,OAAO2B,eAAe,CAAC,kBAAkB,CAAC;YAEvEF,WAAWG,YAAY,CAACC,GAAG,CAAC,SAASN;YAErC,OAAO;gBAACO,aAAaL,WAAWM,QAAQ;YAAE;QAC5C;IACF;IAEA,MAAMC,mBAAmBjC,YAAY;QACnCY,QAAQ;QACRC,MAAM;QACNC,MAAMrB;QACNsB,aAAa;QACbC,QAAQ;YACNkB,aAAapC;YACboB,UAAU;gBACR,KAAKnB;YACP;QACF;QACAoC,cAAc9B;QACdc,SAAS,OAAOC;YACd,MAAMG,QAAQ7B,mBAAmB0B;YACjC,MAAMgB,aAAa,MAAMlC,qBAAqB;gBAC5CK;gBACA8B,MAAMjB,QAAQkB,KAAK,CAACD,IAAI;gBACxBE,gBAAgBnB,QAAQkB,KAAK,CAACE,eAAe;gBAC7ChB,OAAOJ,QAAQkB,KAAK,CAACd,KAAK;gBAC1BiB,eAAelB,MAAME,MAAM;gBAC3BiB,oBAAoBnB,MAAMoB,WAAW;gBACrCC,4BACElC,oCAAoCmC;gBACtCrC;gBACAC;YACF;YAEA,OAAOL,2BAA2BgC;QACpC;IACF;IAEA,OAAO;QACLU,QAAQ;QACRC,QAAQ;YAACpC;YAAoBsB;SAAiB;IAChD;AACF;AAEA,SAASY,oCAAoCG,MAI5C;IACC,OAAOC,QAAQC,MAAM,CAAC,IAAIC,MAAM;AAClC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, PublishSourcePushFn, RecordDeliveryOnlyFn } from '@shipfox/api-integration-
|
|
1
|
+
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, PublishSourcePushFn, 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';
|
|
@@ -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,
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES } from '@shipfox/api-integration-
|
|
2
|
+
import { createStoredWebhookRequest, WEBHOOK_MAX_RAW_BODY_BYTES } from '@shipfox/api-integration-spi';
|
|
3
3
|
import { ClientError, defineRoute, rawBodyPlugin, WEBHOOK_BODY_LIMIT } from '@shipfox/node-fastify';
|
|
4
4
|
import { createGithubWebhookProcessor } from '#core/webhook-processor.js';
|
|
5
5
|
const SIGNATURE_HEADER = 'x-hub-signature-256';
|
|
@@ -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-
|
|
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":"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"}
|