Break out github into it’s own package

This commit is contained in:
Eric Allam
2023-01-30 12:57:37 +00:00
parent 71549606ad
commit 2d0e766b1a
40 changed files with 2800 additions and 54 deletions
@@ -4,8 +4,8 @@ import {
SlackInteractionSourceSchema,
} from "@trigger.dev/common-schemas";
import cronstrue from "cronstrue";
import type { DisplayProperties } from "internal-integrations";
import { github } from "internal-integrations";
import type { DisplayProperties } from "@trigger.dev/integration-sdk";
import * as github from "@trigger.dev/github/internal";
import invariant from "tiny-invariant";
import { triggerLabel } from "~/components/triggers/triggerLabel";
import type { PrismaClient } from "~/db.server";
@@ -1,8 +1,8 @@
import type { PrismaClient } from "~/db.server";
import { prisma } from "~/db.server";
import { github } from "internal-integrations";
import * as github from "@trigger.dev/github/internal";
import type { ExternalSourceWithConnection } from "~/models/externalSource.server";
import type { NormalizedRequest } from "internal-integrations";
import type { NormalizedRequest } from "@trigger.dev/integration-sdk";
import { IngestEvent } from "../events/ingest.server";
import { ManualWebhookSourceSchema } from "@trigger.dev/common-schemas";
import { createHmac, timingSafeEqual } from "node:crypto";
@@ -1,10 +1,9 @@
import type { APIConnection, ExternalSource } from ".prisma/client";
import type { AccessInfo } from "internal-integrations";
import { github } from "internal-integrations";
import type { AccessInfo } from "@trigger.dev/integration-sdk";
import * as github from "@trigger.dev/github/internal";
import crypto from "node:crypto";
import type { PrismaClient } from "~/db.server";
import { prisma } from "~/db.server";
import { env } from "~/env.server";
import {
buildExternalSourceUrl,
findExternalSourceById,
@@ -4,7 +4,7 @@ import { FetchRequestSchema } from "@trigger.dev/common-schemas";
import type {
NormalizedResponse,
PerformedRequestResponse,
} from "internal-integrations";
} from "@trigger.dev/integration-sdk";
import type { z } from "zod";
import type { PrismaClient } from "~/db.server";
import { prisma } from "~/db.server";
@@ -3,7 +3,7 @@ import type {
CacheService,
NormalizedResponse,
PerformedRequestResponse,
} from "internal-integrations";
} from "@trigger.dev/integration-sdk";
import { resend, shopify, slack } from "internal-integrations";
import type { PrismaClient } from "~/db.server";
import { prisma } from "~/db.server";
@@ -1,4 +1,4 @@
import { github } from "internal-integrations";
import * as github from "@trigger.dev/github/internal";
import type { WorkflowMetadata } from "internal-platform";
import { WorkflowMetadataSchema } from "internal-platform";
import crypto from "node:crypto";
+3 -1
View File
@@ -64,6 +64,7 @@
"@tanstack/react-table": "^8.0.0-alpha.87",
"@trigger.dev/common-schemas": "workspace:*",
"@trigger.dev/providers": "workspace:*",
"@trigger.dev/github": "workspace:*",
"@typeform/embed-react": "^2.14.1",
"@uiw/react-codemirror": "^4.13.2",
"bcryptjs": "^2.4.3",
@@ -134,6 +135,7 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@trigger.dev/tailwind-config": "workspace:*",
"@trigger.dev/integration-sdk": "workspace:*",
"@types/bcryptjs": "^2.4.2",
"@types/compression": "^1.7.2",
"@types/eslint": "^8.4.6",
@@ -186,4 +188,4 @@
"engines": {
"node": ">=16.0.0"
}
}
}
+3
View File
@@ -14,9 +14,11 @@ module.exports = {
"internal-integrations",
"internal-bridge",
"@trigger.dev/providers",
"@trigger.dev/github",
"@trigger.dev/common-schemas",
"@trigger.dev/sdk",
"@trigger.dev/integrations",
"@trigger.dev/integration-sdk",
"emails",
"internal-pulsar",
],
@@ -32,6 +34,7 @@ module.exports = {
"../../packages/internal-platform/src/**/*",
"../../packages/trigger-sdk/src/**/*",
"../../packages/trigger-integrations/src/**/*",
"../../integrations/github/src/**/*",
];
},
};
+9 -1
View File
@@ -43,7 +43,15 @@
"emails": ["../../packages/emails/src/index"],
"emails/*": ["../../packages/emails/src/*"],
"internal-pulsar": ["../../packages/internal-pulsar/src/index"],
"internal-pulsar/*": ["../../packages/internal-pulsar/src/*"]
"internal-pulsar/*": ["../../packages/internal-pulsar/src/*"],
"@trigger.dev/integration-sdk": [
"../../packages/integration-sdk/src/index"
],
"@trigger.dev/integration-sdk/*": [
"../../packages/integration-sdk/src/*"
],
"@trigger.dev/github": ["../../integrations/github/src/index"],
"@trigger.dev/github/*": ["../../integrations/github/src/*"]
},
"noEmit": true
}
+17 -4
View File
@@ -11,18 +11,31 @@
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": ["esnext", "dom"],
"lib": [
"esnext",
"dom"
],
"outDir": "lib",
"moduleResolution": "node",
"paths": {
"@trigger.dev/sdk": ["../../packages/trigger-sdk/src/index"],
"@trigger.dev/sdk/*": ["../../packages/trigger-sdk/src/*"],
"@trigger.dev/sdk": [
"../../packages/trigger-sdk/src/index"
],
"@trigger.dev/sdk/*": [
"../../packages/trigger-sdk/src/*"
],
"@trigger.dev/integrations": [
"../../packages/trigger-integrations/src/index"
],
"@trigger.dev/integrations/*": [
"../../packages/trigger-integrations/src/*"
],
"@trigger.dev/github": [
"../../integrations/github/src/index"
],
"@trigger.dev/github/*": [
"../../integrations/github/src/*"
]
}
}
}
}
+2 -2
View File
@@ -4,7 +4,7 @@
"version": "0.0.1",
"description": "Example trigger.dev workflow that uses the Github Webhook integration",
"dependencies": {
"@trigger.dev/integrations": "workspace:*",
"@trigger.dev/github": "workspace:*",
"@trigger.dev/sdk": "workspace:*",
"zod": "^3.20.2"
},
@@ -16,4 +16,4 @@
"scripts": {
"dev": "tsx src/index.ts"
}
}
}
+9 -9
View File
@@ -1,5 +1,5 @@
import { Trigger } from "@trigger.dev/sdk";
import { github } from "@trigger.dev/integrations";
import { events } from "@trigger.dev/github";
new Trigger({
id: "github-webhook-9",
@@ -7,7 +7,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.issueEvent({
on: events.issueEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -23,7 +23,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.issueCommentEvent({
on: events.issueCommentEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -39,7 +39,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.pullRequestEvent({
on: events.pullRequestEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -55,7 +55,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.pullRequestCommentEvent({
on: events.pullRequestCommentEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -71,7 +71,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.pullRequestReviewEvent({
on: events.pullRequestReviewEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -87,7 +87,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.pushEvent({
on: events.pushEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -103,7 +103,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.commitCommentEvent({
on: events.commitCommentEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -119,7 +119,7 @@ new Trigger({
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.newStarEvent({
on: events.newStarEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
+3
View File
@@ -0,0 +1,3 @@
# Trigger.dev GitHub integration
View more documentation [here](https://docs.trigger.dev)
+39
View File
@@ -0,0 +1,39 @@
{
"name": "@trigger.dev/github",
"version": "0.1.16",
"description": "The official GitHub integration for Trigger.dev",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"files": [
"dist"
],
"devDependencies": {
"@trigger.dev/sdk": "workspace:*",
"@trigger.dev/tsconfig": "workspace:*",
"@trigger.dev/integration-sdk": "workspace:*",
"@types/node": "16",
"rimraf": "^3.0.2",
"tsup": "^6.5.0"
},
"peerDependencies": {
"@trigger.dev/sdk": "workspace:*"
},
"scripts": {
"clean": "rimraf dist",
"build": "npm run clean && npm run build:tsup",
"build:tsup": "tsup"
},
"dependencies": {
"@octokit/webhooks": "^10.4.0",
"zod": "^3.20.2"
}
}
+239
View File
@@ -0,0 +1,239 @@
import type { TriggerEvent } from "@trigger.dev/sdk";
import * as schemas from "./schemas";
export function commitCommentEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.commitComments.commitCommentEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "commit_comment",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["commit_comment"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["commit_comment"],
}),
manualRegistration: false,
},
schema: schemas.commitComments.commitCommentEventSchema,
};
}
export function issueEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.issues.issuesEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "issues",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["issues"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["issues"],
}),
manualRegistration: false,
},
schema: schemas.issues.issuesEventSchema,
};
}
export function issueCommentEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.issuesComments.issueCommentEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "issue_comment",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["issue_comment"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["issue_comment"],
}),
manualRegistration: false,
},
schema: schemas.issuesComments.issueCommentEventSchema,
};
}
export function pullRequestEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.pullRequest.pullRequestEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "pull_request",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["pull_request"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["pull_request"],
}),
manualRegistration: false,
},
schema: schemas.pullRequest.pullRequestEventSchema,
};
}
export function pullRequestCommentEvent(params: {
repo: string;
}): TriggerEvent<
typeof schemas.pullRequestComments.pullRequestReviewCommentEventSchema
> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "pull_request_review_comment",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["pull_request_review_comment"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["pull_request_review_comment"],
}),
manualRegistration: false,
},
schema: schemas.pullRequestComments.pullRequestReviewCommentEventSchema,
};
}
export function pullRequestReviewEvent(params: {
repo: string;
}): TriggerEvent<
typeof schemas.pullRequestReviews.pullRequestReviewEventSchema
> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "pull_request_review",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["pull_request_review"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["pull_request_review"],
}),
manualRegistration: false,
},
schema: schemas.pullRequestReviews.pullRequestReviewEventSchema,
};
}
export function pushEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.push.pushEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "push",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["push"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["push"],
}),
manualRegistration: false,
},
schema: schemas.push.pushEventSchema,
};
}
export function newStarEvent(params: {
repo: string;
}): TriggerEvent<typeof schemas.stars.starCreatedEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "star",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
action: ["created"],
},
event: ["star"],
},
source: schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["star"],
}),
manualRegistration: false,
},
schema: schemas.stars.starCreatedEventSchema,
};
}
+3
View File
@@ -0,0 +1,3 @@
import * as events from "./events";
export { events };
+16
View File
@@ -0,0 +1,16 @@
import { GitHubWebhookIntegration } from "./webhooks";
import * as schemas from "./schemas";
export const provider = {
name: "GitHub",
slug: "github",
icon: "/integrations/github.png",
enabledFor: "all",
authentication: {
type: "oauth",
scopes: ["repo"],
},
schemas,
};
export const webhooks = new GitHubWebhookIntegration();
@@ -0,0 +1,31 @@
import { z } from "zod";
import {
userSchema,
authorAssociationSchema,
repositorySchema,
installationLiteSchema,
organizationSchema,
} from "./shared";
export const commitCommentEventSchema = z.object({
action: z.literal("created"),
comment: z.object({
url: z.string(),
html_url: z.string(),
id: z.number(),
node_id: z.string(),
user: userSchema,
position: z.number().nullable(),
line: z.number().nullable(),
path: z.string().nullable(),
commit_id: z.string(),
created_at: z.string(),
updated_at: z.string(),
author_association: authorAssociationSchema,
body: z.string(),
}),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
+39
View File
@@ -0,0 +1,39 @@
import { z } from "zod";
import * as commitComments from "./commitComments";
import * as issuesComments from "./issueComments";
import * as issues from "./issues";
import * as pullRequestComments from "./pullRequestComments";
import * as pullRequestReviews from "./pullRequestReviews";
import * as pullRequest from "./pullRequests";
import * as push from "./pushes";
import * as stars from "./stars";
export const WebhookRepoSourceSchema = z.object({
subresource: z.literal("repository"),
scopes: z.array(z.string()),
repo: z.string(),
events: z.array(z.string()),
});
export const WebhookOrganizationSourceSchema = z.object({
subresource: z.literal("organization"),
scopes: z.array(z.string()),
org: z.string(),
events: z.array(z.string()),
});
export const WebhookSourceSchema = z.union([
WebhookRepoSourceSchema,
WebhookOrganizationSourceSchema,
]);
export {
commitComments,
issues,
issuesComments,
pullRequest,
pullRequestComments,
pullRequestReviews,
push,
stars,
};
@@ -0,0 +1,91 @@
import { z } from "zod";
import { issueSchema } from "./issues";
import {
appSchema,
authorAssociationSchema,
installationLiteSchema,
labelSchema,
organizationSchema,
reactionsSchema,
repositorySchema,
userSchema,
} from "./shared";
export const issueCommentSchema = z.object({
url: z.string(),
html_url: z.string(),
issue_url: z.string(),
id: z.number(),
node_id: z.string(),
user: userSchema,
created_at: z.string(),
updated_at: z.string(),
author_association: authorAssociationSchema,
body: z.string(),
reactions: reactionsSchema,
performed_via_github_app: appSchema.nullable(),
});
export const issueCommentCreatedEventSchema = z.object({
action: z.literal("created"),
issue: issueSchema.and(
z.object({
assignee: userSchema.nullable(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
labels: z.array(labelSchema),
})
),
comment: issueCommentSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issueCommentDeletedEventSchema = z.object({
action: z.literal("deleted"),
issue: issueSchema.and(
z.object({
assignee: userSchema.nullable(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
labels: z.array(labelSchema),
})
),
comment: issueCommentSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issueCommentEditedEventSchema = z.object({
action: z.literal("edited"),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
}),
issue: issueSchema.and(
z.object({
assignee: userSchema.nullable(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
labels: z.array(labelSchema),
})
),
comment: issueCommentSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issueCommentEventSchema = z.discriminatedUnion("action", [
issueCommentCreatedEventSchema,
issueCommentDeletedEventSchema,
issueCommentEditedEventSchema,
]);
+311
View File
@@ -0,0 +1,311 @@
import { z } from "zod";
import {
appSchema,
authorAssociationSchema,
installationLiteSchema,
labelSchema,
milestoneSchema,
organizationSchema,
reactionsSchema,
repositorySchema,
userSchema,
} from "./shared";
export const issueSchema = z.object({
url: z.string(),
repository_url: z.string(),
labels_url: z.string(),
comments_url: z.string(),
events_url: z.string(),
html_url: z.string(),
id: z.number(),
node_id: z.string(),
number: z.number(),
title: z.string(),
user: userSchema,
labels: z.array(labelSchema).optional(),
state: z.union([z.literal("open"), z.literal("closed")]).optional(),
locked: z.boolean().optional(),
assignee: userSchema.optional().nullable(),
assignees: z.array(userSchema),
milestone: milestoneSchema.nullable(),
comments: z.number(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
author_association: authorAssociationSchema,
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
draft: z.boolean().optional(),
performed_via_github_app: appSchema.optional().nullable(),
pull_request: z
.object({
url: z.string().optional(),
html_url: z.string().optional(),
diff_url: z.string().optional(),
patch_url: z.string().optional(),
merged_at: z.string().optional().nullable(),
})
.optional(),
body: z.string().nullable(),
reactions: reactionsSchema,
timeline_url: z.string().optional(),
state_reason: z.string().optional().nullable(),
});
export const issuesAssignedEventSchema = z.object({
action: z.literal("assigned"),
issue: issueSchema,
assignee: userSchema.optional().nullable(),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesClosedEventSchema = z.object({
action: z.literal("closed"),
issue: issueSchema.and(
z.object({
state: z.literal("closed"),
closed_at: z.string(),
})
),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesDeletedEventSchema = z.object({
action: z.literal("deleted"),
issue: issueSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesDemilestonedEventSchema = z.object({
action: z.literal("demilestoned"),
issue: issueSchema.and(
z.object({
milestone: z.null(),
})
),
milestone: milestoneSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesEditedEventSchema = z.object({
action: z.literal("edited"),
issue: issueSchema,
label: labelSchema.optional(),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
title: z
.object({
from: z.string(),
})
.optional(),
}),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesLabeledEventSchema = z.object({
action: z.literal("labeled"),
issue: issueSchema,
label: labelSchema.optional(),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesLockedEventSchema = z.object({
action: z.literal("locked"),
issue: issueSchema.and(
z.object({
locked: z.literal(true),
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
})
),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesMilestonedEventSchema = z.object({
action: z.literal("milestoned"),
issue: issueSchema.and(
z.object({
milestone: milestoneSchema,
})
),
milestone: milestoneSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesOpenedEventSchema = z.object({
action: z.literal("opened"),
changes: z
.object({
old_issue: issueSchema,
old_repository: repositorySchema,
})
.optional(),
issue: issueSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
})
),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesPinnedEventSchema = z.object({
action: z.literal("pinned"),
issue: issueSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesReopenedEventSchema = z.object({
action: z.literal("reopened"),
issue: issueSchema.and(
z.object({
state: z.literal("open"),
})
),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesTransferredEventSchema = z.object({
action: z.literal("transferred"),
changes: z.object({
new_issue: issueSchema,
new_repository: repositorySchema,
}),
issue: issueSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesUnassignedEventSchema = z.object({
action: z.literal("unassigned"),
issue: issueSchema,
assignee: userSchema.optional().nullable(),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesUnlabeledEventSchema = z.object({
action: z.literal("unlabeled"),
issue: issueSchema,
label: labelSchema.optional(),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesUnlockedEventSchema = z.object({
action: z.literal("unlocked"),
issue: issueSchema.and(
z.object({
locked: z.literal(false),
active_lock_reason: z.null(),
})
),
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesUnpinnedEventSchema = z.object({
action: z.literal("unpinned"),
issue: issueSchema,
repository: repositorySchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
export const issuesEventSchema: z.ZodDiscriminatedUnion<
"action",
[
typeof issuesAssignedEventSchema,
typeof issuesClosedEventSchema,
typeof issuesDeletedEventSchema,
typeof issuesDemilestonedEventSchema,
typeof issuesEditedEventSchema,
typeof issuesLabeledEventSchema,
typeof issuesLockedEventSchema,
typeof issuesMilestonedEventSchema,
typeof issuesOpenedEventSchema,
typeof issuesPinnedEventSchema,
typeof issuesReopenedEventSchema,
typeof issuesTransferredEventSchema,
typeof issuesUnassignedEventSchema,
typeof issuesUnlabeledEventSchema,
typeof issuesUnlockedEventSchema,
typeof issuesUnpinnedEventSchema
]
> = z.discriminatedUnion("action", [
issuesAssignedEventSchema,
issuesClosedEventSchema,
issuesDeletedEventSchema,
issuesDemilestonedEventSchema,
issuesEditedEventSchema,
issuesLabeledEventSchema,
issuesLockedEventSchema,
issuesMilestonedEventSchema,
issuesOpenedEventSchema,
issuesPinnedEventSchema,
issuesReopenedEventSchema,
issuesTransferredEventSchema,
issuesUnassignedEventSchema,
issuesUnlabeledEventSchema,
issuesUnlockedEventSchema,
issuesUnpinnedEventSchema,
]);
@@ -0,0 +1,285 @@
import { z } from "zod";
import {
userSchema,
teamSchema,
labelSchema,
milestoneSchema,
repositorySchema,
linkSchema,
authorAssociationSchema,
installationLiteSchema,
organizationSchema,
reactionsSchema,
pullRequestAutoMergeSchema,
} from "./shared";
export const pullRequestReviewCommentSchema = z.object({
url: z.string(),
pull_request_review_id: z.number(),
id: z.number(),
node_id: z.string(),
diff_hunk: z.string(),
path: z.string(),
position: z.number().nullable(),
original_position: z.number(),
commit_id: z.string(),
original_commit_id: z.string(),
user: userSchema,
body: z.string(),
created_at: z.string(),
updated_at: z.string(),
html_url: z.string(),
pull_request_url: z.string(),
author_association: authorAssociationSchema,
_links: z.object({
self: linkSchema,
html: linkSchema,
pull_request: linkSchema,
}),
reactions: reactionsSchema,
start_line: z.number().nullable(),
original_start_line: z.number().nullable(),
start_side: z.union([z.literal("LEFT"), z.literal("RIGHT")]).nullable(),
line: z.number().nullable(),
original_line: z.number(),
side: z.union([z.literal("LEFT"), z.literal("RIGHT")]),
in_reply_to_id: z.number().optional(),
});
export const pullRequestReviewCommentCreatedEventSchema = z.object({
action: z.literal("created"),
comment: pullRequestReviewCommentSchema,
pull_request: z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
draft: z.boolean().optional(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
author_association: authorAssociationSchema,
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
}),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewCommentDeletedEventSchema = z.object({
action: z.literal("deleted"),
comment: pullRequestReviewCommentSchema,
pull_request: z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
draft: z.boolean().optional(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
author_association: authorAssociationSchema,
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
}),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewCommentEditedEventSchema = z.object({
action: z.literal("edited"),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
}),
comment: pullRequestReviewCommentSchema,
pull_request: z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
draft: z.boolean().optional(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
auto_merge: pullRequestAutoMergeSchema.optional().nullable(),
author_association: authorAssociationSchema,
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
}),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewCommentEventSchema = z.union([
pullRequestReviewCommentCreatedEventSchema,
pullRequestReviewCommentDeletedEventSchema,
pullRequestReviewCommentEditedEventSchema,
]);
@@ -0,0 +1,79 @@
import { z } from "zod";
import {
repositorySchema,
installationLiteSchema,
organizationSchema,
userSchema,
authorAssociationSchema,
linkSchema,
simplePullRequestSchema,
} from "./shared";
export const pullRequestReviewSchema = z.object({
id: z.number(),
node_id: z.string(),
user: userSchema,
body: z.string().nullable(),
commit_id: z.string(),
submitted_at: z.string().nullable(),
state: z.union([
z.literal("commented"),
z.literal("changes_requested"),
z.literal("approved"),
z.literal("dismissed"),
]),
html_url: z.string(),
pull_request_url: z.string(),
author_association: authorAssociationSchema,
_links: z.object({
html: linkSchema,
pull_request: linkSchema,
}),
});
export const pullRequestReviewDismissedEventSchema = z.object({
action: z.literal("dismissed"),
review: pullRequestReviewSchema.and(
z.object({
state: z.literal("dismissed"),
})
),
pull_request: simplePullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewEditedEventSchema = z.object({
action: z.literal("edited"),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
}),
review: pullRequestReviewSchema,
pull_request: simplePullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewSubmittedEventSchema = z.object({
action: z.literal("submitted"),
review: pullRequestReviewSchema,
pull_request: simplePullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewEventSchema = z.union([
pullRequestReviewDismissedEventSchema,
pullRequestReviewEditedEventSchema,
pullRequestReviewSubmittedEventSchema,
]);
@@ -0,0 +1,401 @@
import { z } from "zod";
import {
authorAssociationSchema,
installationLiteSchema,
labelSchema,
linkSchema,
milestoneSchema,
organizationSchema,
pullRequestAutoMergeSchema,
repositorySchema,
teamSchema,
userSchema,
} from "./shared";
export const pullRequestSchema = z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
author_association: authorAssociationSchema,
auto_merge: pullRequestAutoMergeSchema.nullable(),
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
draft: z.boolean(),
merged: z.boolean().nullable(),
mergeable: z.boolean().nullable(),
rebaseable: z.boolean().nullable(),
mergeable_state: z.string(),
merged_by: userSchema.nullable(),
comments: z.number(),
review_comments: z.number(),
maintainer_can_modify: z.boolean(),
commits: z.number(),
additions: z.number(),
deletions: z.number(),
changed_files: z.number(),
});
export const pullRequestAssignedEventSchema = z.object({
action: z.literal("assigned"),
number: z.number(),
pull_request: pullRequestSchema,
assignee: userSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestAutoMergeDisabledEventSchema = z.object({
action: z.literal("auto_merge_disabled"),
number: z.number(),
pull_request: pullRequestSchema,
reason: z.string(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestAutoMergeEnabledEventSchema = z.object({
action: z.literal("auto_merge_enabled"),
number: z.number(),
pull_request: pullRequestSchema,
reason: z.string(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestClosedEventSchema = z.object({
action: z.literal("closed"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("closed"),
closed_at: z.string(),
merged: z.boolean(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestConvertedToDraftEventSchema = z.object({
action: z.literal("converted_to_draft"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
closed_at: z.null(),
merged_at: z.null(),
draft: z.literal(true),
merged: z.literal(false),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestDequeuedEventSchema = z.object({
action: z.literal("dequeued"),
number: z.number(),
reason: z.string(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestEditedEventSchema = z.object({
action: z.literal("edited"),
number: z.number(),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
title: z
.object({
from: z.string(),
})
.optional(),
base: z
.object({
ref: z.object({
from: z.string(),
}),
sha: z.object({
from: z.string(),
}),
})
.optional(),
}),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestLabeledEventSchema = z.object({
action: z.literal("labeled"),
number: z.number(),
pull_request: pullRequestSchema,
label: labelSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestLockedEventSchema = z.object({
action: z.literal("locked"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestOpenedEventSchema = z.object({
action: z.literal("opened"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
active_lock_reason: z.null(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestQueuedEventSchema = z.object({
action: z.literal("queued"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReadyForReviewEventSchema = z.object({
action: z.literal("ready_for_review"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
draft: z.literal(false),
merged: z.boolean(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReopenedEventSchema = z.object({
action: z.literal("reopened"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
merged: z.boolean(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestSynchronizeEventSchema = z.object({
action: z.literal("synchronize"),
number: z.number(),
before: z.string(),
after: z.string(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnassignedEventSchema = z.object({
action: z.literal("unassigned"),
number: z.number(),
pull_request: pullRequestSchema,
assignee: userSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnlabeledEventSchema = z.object({
action: z.literal("unlabeled"),
number: z.number(),
pull_request: pullRequestSchema,
label: labelSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnlockedEventSchema = z.object({
action: z.literal("unlocked"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewRequestRemovedEventSchema = z.object({
action: z.literal("review_request_removed"),
number: z.number(),
pull_request: pullRequestSchema,
requested_reviewer: userSchema.optional(),
requested_team: teamSchema.optional(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewRequestedEventSchema = z.object({
action: z.literal("review_requested"),
number: z.number(),
pull_request: pullRequestSchema,
requested_reviewer: userSchema.optional(),
requested_team: teamSchema.optional(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestEventSchema: z.ZodDiscriminatedUnion<
"action",
[
typeof pullRequestAssignedEventSchema,
typeof pullRequestAutoMergeDisabledEventSchema,
typeof pullRequestAutoMergeEnabledEventSchema,
typeof pullRequestClosedEventSchema,
typeof pullRequestConvertedToDraftEventSchema,
typeof pullRequestDequeuedEventSchema,
typeof pullRequestEditedEventSchema,
typeof pullRequestLabeledEventSchema,
typeof pullRequestLockedEventSchema,
typeof pullRequestOpenedEventSchema,
typeof pullRequestQueuedEventSchema,
typeof pullRequestReadyForReviewEventSchema,
typeof pullRequestReopenedEventSchema,
typeof pullRequestReviewRequestRemovedEventSchema,
typeof pullRequestReviewRequestedEventSchema,
typeof pullRequestSynchronizeEventSchema,
typeof pullRequestUnassignedEventSchema,
typeof pullRequestUnlabeledEventSchema,
typeof pullRequestUnlockedEventSchema
]
> = z.discriminatedUnion("action", [
pullRequestAssignedEventSchema,
pullRequestAutoMergeDisabledEventSchema,
pullRequestAutoMergeEnabledEventSchema,
pullRequestClosedEventSchema,
pullRequestConvertedToDraftEventSchema,
pullRequestDequeuedEventSchema,
pullRequestEditedEventSchema,
pullRequestLabeledEventSchema,
pullRequestLockedEventSchema,
pullRequestOpenedEventSchema,
pullRequestQueuedEventSchema,
pullRequestReadyForReviewEventSchema,
pullRequestReopenedEventSchema,
pullRequestReviewRequestRemovedEventSchema,
pullRequestReviewRequestedEventSchema,
pullRequestSynchronizeEventSchema,
pullRequestUnassignedEventSchema,
pullRequestUnlabeledEventSchema,
pullRequestUnlockedEventSchema,
]);
+27
View File
@@ -0,0 +1,27 @@
import { z } from "zod";
import {
repositorySchema,
userSchema,
installationLiteSchema,
organizationSchema,
commitSchema,
committerSchema,
} from "./shared";
export const pushEventSchema = z.object({
ref: z.string(),
before: z.string(),
after: z.string(),
created: z.boolean(),
deleted: z.boolean(),
forced: z.boolean(),
base_ref: z.string().nullable(),
compare: z.string(),
commits: z.array(commitSchema),
head_commit: commitSchema.nullable(),
repository: repositorySchema,
pusher: committerSchema,
sender: userSchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
});
+507
View File
@@ -0,0 +1,507 @@
import { z } from "zod";
export const userSchema = z.object({
login: z.string(),
id: z.number(),
node_id: z.string(),
name: z.string().optional(),
email: z.string().optional().nullable(),
avatar_url: z.string(),
gravatar_id: z.string(),
url: z.string(),
html_url: z.string(),
followers_url: z.string(),
following_url: z.string(),
gists_url: z.string(),
starred_url: z.string(),
subscriptions_url: z.string(),
organizations_url: z.string(),
repos_url: z.string(),
events_url: z.string(),
received_events_url: z.string(),
type: z.union([
z.literal("Bot"),
z.literal("User"),
z.literal("Organization"),
]),
site_admin: z.boolean(),
});
export const licenseSchema = z.object({
key: z.string(),
name: z.string(),
spdx_id: z.string(),
url: z.string().nullable(),
node_id: z.string(),
});
export const installationLiteSchema = z.object({
id: z.number(),
node_id: z.string(),
});
export const organizationSchema = z.object({
login: z.string(),
id: z.number(),
node_id: z.string(),
url: z.string(),
html_url: z.string().optional(),
repos_url: z.string(),
events_url: z.string(),
hooks_url: z.string(),
issues_url: z.string(),
members_url: z.string(),
public_members_url: z.string(),
avatar_url: z.string(),
description: z.string().nullable(),
});
export const repositorySchema = z.object({
id: z.number(),
node_id: z.string(),
name: z.string(),
full_name: z.string(),
private: z.boolean(),
owner: userSchema,
html_url: z.string(),
description: z.string().nullable(),
fork: z.boolean(),
url: z.string(),
forks_url: z.string(),
keys_url: z.string(),
collaborators_url: z.string(),
teams_url: z.string(),
hooks_url: z.string(),
issue_events_url: z.string(),
events_url: z.string(),
assignees_url: z.string(),
branches_url: z.string(),
tags_url: z.string(),
blobs_url: z.string(),
git_tags_url: z.string(),
git_refs_url: z.string(),
trees_url: z.string(),
statuses_url: z.string(),
languages_url: z.string(),
stargazers_url: z.string(),
contributors_url: z.string(),
subscribers_url: z.string(),
subscription_url: z.string(),
commits_url: z.string(),
git_commits_url: z.string(),
comments_url: z.string(),
issue_comment_url: z.string(),
contents_url: z.string(),
compare_url: z.string(),
merges_url: z.string(),
archive_url: z.string(),
downloads_url: z.string(),
issues_url: z.string(),
pulls_url: z.string(),
milestones_url: z.string(),
notifications_url: z.string(),
labels_url: z.string(),
releases_url: z.string(),
deployments_url: z.string(),
created_at: z.union([z.number(), z.string()]),
updated_at: z.string(),
pushed_at: z.union([z.number(), z.string()]).nullable(),
git_url: z.string(),
ssh_url: z.string(),
clone_url: z.string(),
svn_url: z.string(),
homepage: z.string().nullable(),
size: z.number(),
stargazers_count: z.number(),
watchers_count: z.number(),
language: z.string().nullable(),
has_issues: z.boolean(),
has_projects: z.boolean(),
has_downloads: z.boolean(),
has_wiki: z.boolean(),
has_pages: z.boolean(),
forks_count: z.number(),
mirror_url: z.string().nullable(),
archived: z.boolean(),
disabled: z.boolean().optional(),
open_issues_count: z.number(),
license: licenseSchema.nullable(),
forks: z.number(),
open_issues: z.number(),
watchers: z.number(),
stargazers: z.number().optional(),
default_branch: z.string(),
allow_squash_merge: z.boolean().optional(),
allow_merge_commit: z.boolean().optional(),
allow_rebase_merge: z.boolean().optional(),
allow_auto_merge: z.boolean().optional(),
allow_forking: z.boolean().optional(),
allow_update_branch: z.boolean().optional(),
use_squash_pr_title_as_default: z.boolean().optional(),
squash_merge_commit_message: z.string().optional(),
squash_merge_commit_title: z.string().optional(),
merge_commit_message: z.string().optional(),
merge_commit_title: z.string().optional(),
is_template: z.boolean(),
web_commit_signoff_required: z.boolean(),
topics: z.array(z.string()),
visibility: z.union([
z.literal("public"),
z.literal("private"),
z.literal("internal"),
]),
delete_branch_on_merge: z.boolean().optional(),
master_branch: z.string().optional(),
permissions: z
.object({
pull: z.boolean(),
push: z.boolean(),
admin: z.boolean(),
maintain: z.boolean().optional(),
triage: z.boolean().optional(),
})
.optional(),
public: z.boolean().optional(),
organization: z.string().optional(),
});
export const teamSchema = z.object({
name: z.string(),
id: z.number(),
node_id: z.string(),
slug: z.string(),
description: z.string().nullable(),
privacy: z.union([
z.literal("open"),
z.literal("closed"),
z.literal("secret"),
]),
url: z.string(),
html_url: z.string(),
members_url: z.string(),
repositories_url: z.string(),
permission: z.string(),
parent: z
.object({
name: z.string(),
id: z.number(),
node_id: z.string(),
slug: z.string(),
description: z.string().nullable(),
privacy: z.union([
z.literal("open"),
z.literal("closed"),
z.literal("secret"),
]),
url: z.string(),
html_url: z.string(),
members_url: z.string(),
repositories_url: z.string(),
permission: z.string(),
})
.optional()
.nullable(),
});
export const linkSchema = z.object({
href: z.string(),
});
export const appSchema = z.object({
id: z.number(),
slug: z.string().optional(),
node_id: z.string(),
owner: userSchema,
name: z.string(),
description: z.string().nullable(),
external_url: z.string(),
html_url: z.string(),
created_at: z.string(),
updated_at: z.string(),
permissions: z
.object({
actions: z.union([z.literal("read"), z.literal("write")]).optional(),
administration: z
.union([z.literal("read"), z.literal("write")])
.optional(),
blocking: z.union([z.literal("read"), z.literal("write")]).optional(),
checks: z.union([z.literal("read"), z.literal("write")]).optional(),
content_references: z
.union([z.literal("read"), z.literal("write")])
.optional(),
contents: z.union([z.literal("read"), z.literal("write")]).optional(),
deployments: z.union([z.literal("read"), z.literal("write")]).optional(),
discussions: z.union([z.literal("read"), z.literal("write")]).optional(),
emails: z.union([z.literal("read"), z.literal("write")]).optional(),
environments: z.union([z.literal("read"), z.literal("write")]).optional(),
issues: z.union([z.literal("read"), z.literal("write")]).optional(),
keys: z.union([z.literal("read"), z.literal("write")]).optional(),
members: z.union([z.literal("read"), z.literal("write")]).optional(),
merge_queues: z.union([z.literal("read"), z.literal("write")]).optional(),
metadata: z.union([z.literal("read"), z.literal("write")]).optional(),
organization_administration: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_hooks: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_packages: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_plan: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_projects: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_secrets: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_self_hosted_runners: z
.union([z.literal("read"), z.literal("write")])
.optional(),
organization_user_blocking: z
.union([z.literal("read"), z.literal("write")])
.optional(),
packages: z.union([z.literal("read"), z.literal("write")]).optional(),
pages: z.union([z.literal("read"), z.literal("write")]).optional(),
pull_requests: z
.union([z.literal("read"), z.literal("write")])
.optional(),
repository_hooks: z
.union([z.literal("read"), z.literal("write")])
.optional(),
repository_projects: z
.union([z.literal("read"), z.literal("write")])
.optional(),
secret_scanning_alerts: z
.union([z.literal("read"), z.literal("write")])
.optional(),
secrets: z.union([z.literal("read"), z.literal("write")]).optional(),
security_events: z
.union([z.literal("read"), z.literal("write")])
.optional(),
security_scanning_alert: z
.union([z.literal("read"), z.literal("write")])
.optional(),
single_file: z.union([z.literal("read"), z.literal("write")]).optional(),
statuses: z.union([z.literal("read"), z.literal("write")]).optional(),
team_discussions: z
.union([z.literal("read"), z.literal("write")])
.optional(),
vulnerability_alerts: z
.union([z.literal("read"), z.literal("write")])
.optional(),
workflows: z.union([z.literal("read"), z.literal("write")]).optional(),
})
.optional(),
events: z
.array(
z.union([
z.literal("branch_protection_rule"),
z.literal("check_run"),
z.literal("check_suite"),
z.literal("code_scanning_alert"),
z.literal("commit_comment"),
z.literal("content_reference"),
z.literal("create"),
z.literal("delete"),
z.literal("deployment"),
z.literal("deployment_review"),
z.literal("deployment_status"),
z.literal("deploy_key"),
z.literal("discussion"),
z.literal("discussion_comment"),
z.literal("fork"),
z.literal("gollum"),
z.literal("issues"),
z.literal("issue_comment"),
z.literal("label"),
z.literal("member"),
z.literal("membership"),
z.literal("merge_group"),
z.literal("merge_queue_entry"),
z.literal("milestone"),
z.literal("organization"),
z.literal("org_block"),
z.literal("page_build"),
z.literal("project"),
z.literal("projects_v2_item"),
z.literal("project_card"),
z.literal("project_column"),
z.literal("public"),
z.literal("pull_request"),
z.literal("pull_request_review"),
z.literal("pull_request_review_comment"),
z.literal("push"),
z.literal("registry_package"),
z.literal("release"),
z.literal("repository"),
z.literal("repository_dispatch"),
z.literal("secret_scanning_alert"),
z.literal("secret_scanning_alert_location"),
z.literal("security_and_analysis"),
z.literal("star"),
z.literal("status"),
z.literal("team"),
z.literal("team_add"),
z.literal("watch"),
z.literal("workflow_dispatch"),
z.literal("workflow_run"),
z.literal("workflow_job"),
])
)
.optional(),
});
export const reactionsSchema = z.object({
url: z.string(),
total_count: z.number(),
"+1": z.number(),
"-1": z.number(),
laugh: z.number(),
hooray: z.number(),
confused: z.number(),
heart: z.number(),
rocket: z.number(),
eyes: z.number(),
});
export const authorAssociationSchema = z.union([
z.literal("COLLABORATOR"),
z.literal("CONTRIBUTOR"),
z.literal("FIRST_TIMER"),
z.literal("FIRST_TIME_CONTRIBUTOR"),
z.literal("MANNEQUIN"),
z.literal("MEMBER"),
z.literal("NONE"),
z.literal("OWNER"),
]);
export const milestoneSchema = z.object({
url: z.string(),
html_url: z.string(),
labels_url: z.string(),
id: z.number(),
node_id: z.string(),
number: z.number(),
title: z.string(),
description: z.string().nullable(),
creator: userSchema,
open_issues: z.number(),
closed_issues: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
created_at: z.string(),
updated_at: z.string(),
due_on: z.string().nullable(),
closed_at: z.string().nullable(),
});
export const labelSchema = z.object({
id: z.number(),
node_id: z.string(),
url: z.string(),
name: z.string(),
description: z.string().nullable(),
color: z.string(),
default: z.boolean(),
});
export const pullRequestAutoMergeSchema = z.object({
enabled_by: userSchema,
merge_method: z.union([
z.literal("merge"),
z.literal("squash"),
z.literal("rebase"),
]),
commit_title: z.string(),
commit_message: z.string(),
});
export const simplePullRequestSchema = z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
draft: z.boolean(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
author_association: authorAssociationSchema,
auto_merge: pullRequestAutoMergeSchema.nullable(),
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
});
export const committerSchema = z.object({
name: z.string(),
email: z.string().nullable(),
date: z.string().optional(),
username: z.string().optional(),
});
export const commitSchema = z.object({
id: z.string(),
tree_id: z.string(),
distinct: z.boolean(),
message: z.string(),
timestamp: z.string(),
url: z.string(),
author: committerSchema,
committer: committerSchema,
added: z.array(z.string()),
modified: z.array(z.string()),
removed: z.array(z.string()),
});
+22
View File
@@ -0,0 +1,22 @@
import { z } from "zod";
import { organizationSchema, repositorySchema, userSchema } from "./shared";
export const starCreatedEventSchema = z.object({
action: z.literal("created"),
starred_at: z.coerce.date(),
repository: repositorySchema,
sender: userSchema,
organization: organizationSchema.optional(),
});
export const starDeletedEventSchema = z.object({
action: z.literal("deleted"),
repository: repositorySchema,
sender: userSchema,
organization: organizationSchema.optional(),
});
export const starEventSchema = z.discriminatedUnion("action", [
starCreatedEventSchema,
starDeletedEventSchema,
]);
View File
+223
View File
@@ -0,0 +1,223 @@
import { Webhooks } from "@octokit/webhooks";
import crypto from "crypto";
import { z } from "zod";
import { getAccessToken } from "@trigger.dev/integration-sdk";
import type {
DisplayProperty,
HandleWebhookOptions,
WebhookConfig,
WebhookIntegration,
} from "@trigger.dev/integration-sdk";
import {
WebhookOrganizationSourceSchema,
WebhookRepoSourceSchema,
WebhookSourceSchema,
} from "./schemas";
export class GitHubWebhookIntegration implements WebhookIntegration {
keyForSource(source: unknown): string {
const githubSource = parseWebhookSource(source);
if (githubSource.subresource === "repository") {
return `repository.${githubSource.repo}.${githubSource.events.join(".")}`;
} else if (githubSource.subresource === "organization") {
return `organization.${githubSource.org}`;
} else {
throw new Error(`Unknown subresource`);
}
}
registerWebhook(config: WebhookConfig, source: unknown) {
const githubSource = parseWebhookSource(source);
if (githubSource.subresource === "repository") {
return registerRepositoryWebhook(config, githubSource);
} else if (githubSource.subresource === "organization") {
return registerOrganizationWebhook(config, githubSource);
} else {
throw new Error(`Unknown subresource`);
}
}
handleWebhookRequest(options: HandleWebhookOptions) {
const deliveryId = options.request.headers["x-github-delivery"];
const hookId = options.request.headers["x-github-hook-id"];
const signature = options.request.headers["x-hub-signature-256"];
if (options.secret && signature) {
const githubWebhooks = new Webhooks({
secret: options.secret,
});
console.log(
`[delivery=${deliveryId}][hook=${hookId}] GitHubWebhookIntegration: Verifying signature ${signature}`
);
if (!githubWebhooks.verify(options.request.body, signature)) {
return {
status: "error" as const,
error: `GitHubWebhookIntegration: Could not verify webhook payload, invalid signature or secret. [deliveryId = ${deliveryId}]]`,
};
}
}
const event = options.request.headers["x-github-event"];
const context = omit(options.request.headers, [
"x-github-event",
"x-github-delivery",
"x-hub-signature-256",
"x-hub-signature",
"content-type",
"content-length",
"accept",
"accept-encoding",
"x-forwarded-proto",
]);
const id = md5Hash([hookId, deliveryId].join("-"));
return {
status: "ok" as const,
data: { id, payload: options.request.body, event, context },
};
}
displayProperties(source: unknown) {
const githubSource = parseWebhookSource(source);
const title = `GitHub ${githubSource.events.join(", ")}`;
let properties: DisplayProperty[] = [];
switch (githubSource.subresource) {
case "repository": {
properties = [
{
key: "Repo",
value: githubSource.repo,
},
];
break;
}
case "organization": {
properties = [
{
key: "Organization",
value: githubSource.org,
},
];
break;
}
default: {
throw new Error(`Unknown subresource`);
}
}
return { title, properties };
}
}
export const webhooks = new GitHubWebhookIntegration();
async function registerRepositoryWebhook(
config: WebhookConfig,
source: z.infer<typeof WebhookRepoSourceSchema>
) {
// Create the webhook in github
const response = await fetch(
`https://api.github.com/repos/${source.repo}/hooks`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/vnd.github+json",
Authorization: `Bearer ${getAccessToken(config.accessInfo)}`,
"X-GitHub-Api-Version": "2022-11-28",
},
body: JSON.stringify({
name: "web",
active: true,
events: source.events,
config: {
url: config.callbackUrl,
content_type: "json",
secret: config.secret,
insecure_ssl: "0",
},
}),
}
);
if (!response.ok) {
throw new Error(`Failed to register webhook: ${response.statusText}`);
}
const webhook = await response.json();
return webhook;
}
async function registerOrganizationWebhook(
config: WebhookConfig,
source: z.infer<typeof WebhookOrganizationSourceSchema>
) {
// Create the webhook in github
const response = await fetch(
`https://api.github.com/orgs/${source.org}/hooks`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/vnd.github+json",
Authorization: `Bearer ${getAccessToken(config.accessInfo)}`,
"X-GitHub-Api-Version": "2022-11-28",
},
body: JSON.stringify({
name: "web",
active: true,
events: source.events,
config: {
url: config.callbackUrl,
content_type: "json",
secret: config.secret,
insecure_ssl: "0",
},
}),
}
);
if (!response.ok) {
throw new Error(`Failed to register webhook: ${response.statusText}`);
}
const webhook = await response.json();
return webhook;
}
function parseWebhookSource(source: unknown) {
return WebhookSourceSchema.parse(source);
}
function omit<T extends Record<string, unknown>, K extends keyof T>(
obj: T,
keys: K[]
): Omit<T, K> {
const result: any = {};
for (const key of Object.keys(obj)) {
if (!keys.includes(key as K)) {
result[key] = obj[key];
}
}
return result;
}
function md5Hash(str: string): string {
const hash = crypto.createHash("md5");
hash.update(str);
return hash.digest("hex");
}
+20
View File
@@ -0,0 +1,20 @@
{
"extends": "@trigger.dev/tsconfig/node16.json",
"include": ["./src/**/*.ts"],
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": ["DOM", "DOM.Iterable", "ES2019"],
"paths": {
"@trigger.dev/sdk/*": ["../../packages/trigger-sdk/src/*"],
"@trigger.dev/sdk": ["../../packages/trigger-sdk/src/index"],
"@trigger.dev/integration-sdk/*": [
"../../packages/integration-sdk/src/*"
],
"@trigger.dev/integration-sdk": [
"../../packages/integration-sdk/src/index"
]
}
},
"exclude": ["node_modules"]
}
+23
View File
@@ -0,0 +1,23 @@
import { defineConfig } from "tsup";
export default defineConfig([
{
name: "main",
entry: ["./src/index.ts"],
outDir: "./dist",
platform: "node",
format: ["cjs"],
legacyOutput: true,
sourcemap: true,
clean: true,
bundle: true,
splitting: false,
dts: true,
treeshake: {
preset: "smallest",
},
external: ["http", "https", "util", "events", "tty", "os", "timers"],
esbuildPlugins: [],
noExternal: ["@trigger.dev/common-schemas"],
},
]);
+1
View File
@@ -0,0 +1 @@
Docs coming soon.
+30
View File
@@ -0,0 +1,30 @@
{
"name": "@trigger.dev/integration-sdk",
"version": "0.1.16",
"description": "trigger.dev SDK for integrations",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"publishConfig": {
"access": "public"
},
"files": [
"dist"
],
"devDependencies": {
"@trigger.dev/tsconfig": "workspace:*",
"@types/debug": "^4.1.7",
"@types/node": "16",
"@types/react": "^18.0.21",
"rimraf": "^3.0.2",
"tsup": "^6.5.0"
},
"scripts": {
"clean": "rimraf dist",
"build": "npm run clean && npm run build:tsup",
"build:tsup": "tsup"
},
"dependencies": {
"debug": "^4.3.4",
"zod": "^3.20.2"
}
}
+15
View File
@@ -0,0 +1,15 @@
export * from "./types";
export * from "./services";
import { AccessInfo } from "./types";
export function getAccessToken(accessInfo: AccessInfo): string {
switch (accessInfo.type) {
case "oauth2": {
return accessInfo.accessToken;
}
case "api_key": {
return accessInfo.api_key;
}
}
}
@@ -0,0 +1,137 @@
import { z } from "zod";
import debug from "debug";
const log = debug("trigger:integrations:services");
export type HttpServiceOptions = {
accessToken: string;
baseUrl: string;
};
export type HttpResponse<
TResponseSchema extends z.ZodTypeAny,
TErrorResponseSchema extends z.ZodTypeAny = z.AnyZodObject
> =
| {
success: true;
statusCode: number;
headers: Record<string, string>;
data: z.infer<TResponseSchema>;
}
| {
success: false;
statusCode: number;
headers: Record<string, string>;
error?: z.infer<TErrorResponseSchema>;
};
export class HttpService {
constructor(private readonly options: HttpServiceOptions) {}
async performRequest<
TResponseSchema extends z.ZodTypeAny,
TBodySchema extends z.ZodTypeAny = z.ZodUndefined
>(
endpoint: HttpEndpoint<TResponseSchema, TBodySchema>,
body?: z.infer<TBodySchema>
): Promise<HttpResponse<TResponseSchema>> {
const url = `${this.options.baseUrl}${endpoint.options.path}`;
const method = endpoint.options.method;
const headers = {
Authorization: `Bearer ${this.options.accessToken}`,
"Content-Type": "application/json; charset=utf-8",
};
const actualBody = body ? JSON.stringify(body) : undefined;
const response = await fetch(url, {
method,
headers,
body: actualBody,
});
log(
"%s%s response %d",
this.options.baseUrl,
endpoint.options.path,
response.status
);
const json = await this.#safeGetJson(response);
if (json) {
log(
"%s%s response %O",
this.options.baseUrl,
endpoint.options.path,
json
);
const parsedJson = endpoint.options.response.safeParse(json);
if (parsedJson.success) {
return {
success: true,
data: parsedJson.data,
statusCode: response.status,
headers: normalizeHeaders(response.headers),
};
}
log(
"response json failed to parse %O, errors: %O",
parsedJson,
parsedJson.error
);
return {
success: false,
statusCode: response.status,
headers: normalizeHeaders(response.headers),
error: { type: "zod-parse", issues: parsedJson.error.issues },
};
}
return {
success: false,
statusCode: response.status,
headers: normalizeHeaders(response.headers),
};
}
#safeGetJson = async (response: Response) => {
try {
return await response.json();
} catch (error) {
return undefined;
}
};
}
export type HttpEndpointOptions<
TResponseSchema extends z.ZodTypeAny,
TBodySchema extends z.ZodTypeAny = z.ZodUndefined
> = {
response: TResponseSchema;
body?: TBodySchema;
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
path: string;
};
export class HttpEndpoint<
TResponseSchema extends z.ZodTypeAny,
TBodySchema extends z.ZodTypeAny = z.ZodUndefined
> {
constructor(
public options: HttpEndpointOptions<TResponseSchema, TBodySchema>
) {}
}
function normalizeHeaders(headers: Headers): Record<string, string> {
const normalizedHeaders: Record<string, string> = {};
headers.forEach((value, key) => {
normalizedHeaders[key.toLowerCase()] = value;
});
return normalizedHeaders;
}
+91
View File
@@ -0,0 +1,91 @@
import type { ReactNode } from "react";
export type AccessInfo =
| { type: "oauth2"; accessToken: string }
| {
type: "api_key";
api_key: string;
additionalFields?: Record<string, string>;
};
export interface WebhookConfig {
accessInfo: AccessInfo;
callbackUrl: string;
secret: string;
}
export interface NormalizedRequest {
rawBody: string;
body: any;
headers: Record<string, string>;
searchParams: URLSearchParams;
}
export interface NormalizedResponse {
output: NonNullable<any>;
context: any;
}
export interface HandleWebhookOptions {
request: NormalizedRequest;
secret?: string;
}
export interface ReceivedWebhook {
id: string;
event: string;
payload: any;
timestamp?: string;
context?: any;
}
export type PerformRequestOptions = {
accessInfo: AccessInfo;
endpoint: string;
params: any;
cache?: CacheService;
metadata?: Record<string, string>;
};
export type DisplayProperties = {
title: string;
properties?: DisplayProperty[];
};
export type DisplayProperty = { key: string; value: string | number | boolean };
export interface PerformedRequestResponse {
response: NormalizedResponse;
isRetryable: boolean;
ok: boolean;
}
export interface RequestIntegration {
perform: (
options: PerformRequestOptions
) => Promise<PerformedRequestResponse>;
displayProperties: (endpoint: string, params: any) => DisplayProperties;
renderComponent(input: any, output: any): ReactNode;
}
export interface WebhookIntegration {
keyForSource: (source: unknown) => string;
registerWebhook: (config: WebhookConfig, source: unknown) => Promise<any>;
handleWebhookRequest: (
options: HandleWebhookOptions
) =>
| { status: "ok"; data: ReceivedWebhook }
| { status: "ignored"; reason: string }
| { status: "error"; error: string };
displayProperties: (source: unknown) => DisplayProperties;
}
export interface CacheService {
get: (key: string) => Promise<string | null>;
set: (key: string, value: string, ttl?: number) => Promise<void>;
}
export type InternalIntegration = {
requests?: RequestIntegration;
webhooks?: WebhookIntegration;
};
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "@trigger.dev/tsconfig/node16.json",
"include": ["./src/**/*.ts", "tsup.config.ts"],
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": ["DOM", "DOM.Iterable", "ES2021"]
},
"exclude": ["node_modules"]
}
+19
View File
@@ -0,0 +1,19 @@
import { defineConfig } from "tsup";
export default defineConfig([
{
name: "main",
entry: ["./src/index.ts"],
outDir: "./dist",
platform: "node",
format: ["cjs"],
legacyOutput: true,
sourcemap: true,
clean: true,
bundle: true,
splitting: false,
dts: true,
external: ["http", "https", "util", "events", "tty", "os", "timers"],
esbuildPlugins: [],
},
]);
+85 -27
View File
@@ -75,6 +75,8 @@ importers:
'@testing-library/react': ^13.4.0
'@testing-library/user-event': ^14.4.3
'@trigger.dev/common-schemas': workspace:*
'@trigger.dev/github': workspace:*
'@trigger.dev/integration-sdk': workspace:*
'@trigger.dev/providers': workspace:*
'@trigger.dev/tailwind-config': workspace:*
'@typeform/embed-react': ^2.14.1
@@ -184,7 +186,7 @@ importers:
'@aws-sdk/client-s3': 3.245.0
'@aws-sdk/s3-request-presigner': 3.245.0
'@cfworker/json-schema': 1.12.5
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
'@codemirror/commands': 6.1.3
'@codemirror/lang-javascript': 6.1.2
'@codemirror/lang-json': 6.0.1
@@ -208,9 +210,10 @@ importers:
'@tailwindcss/forms': 0.5.3_tailwindcss@3.1.8
'@tanstack/react-table': 8.7.6_biqbaboplfbrettd7655fr4n2y
'@trigger.dev/common-schemas': link:../../packages/common-schemas
'@trigger.dev/github': link:../../integrations/github
'@trigger.dev/providers': link:../../packages/trigger-providers
'@typeform/embed-react': 2.14.1_react@18.2.0
'@uiw/react-codemirror': 4.19.5_aguurb4bmecpxzejz52amioxne
'@uiw/react-codemirror': 4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle
bcryptjs: 2.4.3
classnames: 2.3.2
clsx: 1.2.1
@@ -277,6 +280,7 @@ importers:
'@testing-library/jest-dom': 5.16.5
'@testing-library/react': 13.4.0_biqbaboplfbrettd7655fr4n2y
'@testing-library/user-event': 14.4.3_ua4wuun3fnehcjqtqj2e2ldgpe
'@trigger.dev/integration-sdk': link:../../packages/integration-sdk
'@trigger.dev/tailwind-config': link:../../config-packages/tailwind-config
'@types/bcryptjs': 2.4.2
'@types/compression': 1.7.2
@@ -406,14 +410,14 @@ importers:
examples/github-webhook:
specifiers:
'@trigger.dev/integrations': workspace:*
'@trigger.dev/github': workspace:*
'@trigger.dev/sdk': workspace:*
'@trigger.dev/tsconfig': workspace:*
'@types/node': '16'
tsx: ^3.12.0
zod: ^3.20.2
dependencies:
'@trigger.dev/integrations': link:../../packages/trigger-integrations
'@trigger.dev/github': link:../../integrations/github
'@trigger.dev/sdk': link:../../packages/trigger-sdk
zod: 3.20.2
devDependencies:
@@ -557,6 +561,27 @@ importers:
'@types/node': 16.18.11
tsx: 3.12.2
integrations/github:
specifiers:
'@octokit/webhooks': ^10.4.0
'@trigger.dev/integration-sdk': workspace:*
'@trigger.dev/sdk': workspace:*
'@trigger.dev/tsconfig': workspace:*
'@types/node': '16'
rimraf: ^3.0.2
tsup: ^6.5.0
zod: ^3.20.2
dependencies:
'@octokit/webhooks': 10.5.1
zod: 3.20.2
devDependencies:
'@trigger.dev/integration-sdk': link:../../packages/integration-sdk
'@trigger.dev/sdk': link:../../packages/trigger-sdk
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
'@types/node': 16.18.11
rimraf: 3.0.2
tsup: 6.5.0
packages/common-schemas:
specifiers:
'@trigger.dev/tsconfig': workspace:*
@@ -613,6 +638,27 @@ importers:
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
'@types/react': 18.0.26
packages/integration-sdk:
specifiers:
'@trigger.dev/tsconfig': workspace:*
'@types/debug': ^4.1.7
'@types/node': '16'
'@types/react': ^18.0.21
debug: ^4.3.4
rimraf: ^3.0.2
tsup: ^6.5.0
zod: ^3.20.2
dependencies:
debug: 4.3.4
zod: 3.20.2
devDependencies:
'@trigger.dev/tsconfig': link:../../config-packages/tsconfig
'@types/debug': 4.1.7
'@types/node': 16.18.11
'@types/react': 18.0.26
rimraf: 3.0.2
tsup: 6.5.0
packages/internal-bridge:
specifiers:
'@trigger.dev/common-schemas': workspace:*
@@ -750,7 +796,7 @@ importers:
tsup: ^6.5.0
zod: ^3.20.2
dependencies:
'@react-email/render': 0.0.3_react@18.2.0
'@react-email/render': 0.0.3
'@trigger.dev/providers': link:../trigger-providers
'@trigger.dev/sdk': link:../trigger-sdk
zod: 3.20.2
@@ -3457,13 +3503,12 @@ packages:
prettier: 2.8.2
dev: false
/@codemirror/autocomplete/6.4.0_eo6pz6bvsllvatnnwfprpuflde:
/@codemirror/autocomplete/6.4.0_czcfkg2f66rxeiodoti7r2gulu:
resolution: {integrity: sha512-HLF2PnZAm1s4kGs30EiqKMgD7XsYaQ0XJnMR0rofEWQ5t5D60SfqpDIkIh1ze5tiEbyUWm8+VJ6W1/erVvBMIA==}
peerDependencies:
'@codemirror/language': ^6.0.0
'@codemirror/state': ^6.0.0
'@codemirror/view': ^6.0.0
'@lezer/common': ^1.0.0
dependencies:
'@codemirror/language': 6.3.2
'@codemirror/state': 6.2.0
@@ -3483,7 +3528,7 @@ packages:
/@codemirror/lang-javascript/6.1.2:
resolution: {integrity: sha512-OcwLfZXdQ1OHrLiIcKCn7MqZ7nx205CMKlhe+vL88pe2ymhT9+2P+QhwkYGxMICj8TDHyp8HFKVwpiisUT7iEQ==}
dependencies:
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
'@codemirror/language': 6.3.2
'@codemirror/lint': 6.1.0
'@codemirror/state': 6.2.0
@@ -4681,6 +4726,16 @@ packages:
react-dom: 18.2.0_react@18.2.0
dev: false
/@react-email/render/0.0.3:
resolution: {integrity: sha512-+4eOrLGdTCJjoJU3PunekErjo3PFnhSDFjVINBHrfJT+1wlVdhWfDo7hFdzXJx/JOOYqmnZTilU/umGLdRumKQ==}
engines: {node: '>=18.0.0'}
dependencies:
pretty: 2.0.0
react-dom: 18.2.0
transitivePeerDependencies:
- react
dev: false
/@react-email/render/0.0.3_react@18.2.0:
resolution: {integrity: sha512-+4eOrLGdTCJjoJU3PunekErjo3PFnhSDFjVINBHrfJT+1wlVdhWfDo7hFdzXJx/JOOYqmnZTilU/umGLdRumKQ==}
engines: {node: '>=18.0.0'}
@@ -4796,7 +4851,7 @@ packages:
eslint: 8.31.0
eslint-import-resolver-node: 0.3.6
eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy
eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq
eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny
eslint-plugin-jest: 26.9.0_ohsifnwenhmxgcp7mend4dnv74
eslint-plugin-jest-dom: 4.0.3_eslint@8.31.0
eslint-plugin-jsx-a11y: 6.7.1_eslint@8.31.0
@@ -5932,18 +5987,17 @@ packages:
eslint-visitor-keys: 3.3.0
dev: true
/@uiw/codemirror-extensions-basic-setup/4.19.5_tbeldtdcrf45b35pezgkzq2u4e:
/@uiw/codemirror-extensions-basic-setup/4.19.5_wd2tsis3in55bkaiwnc2c46tom:
resolution: {integrity: sha512-1zt7ZPJ01xKkSW/KDy0FZNga0bngN1fC594wCVG7FBi60ehfcAucpooQ+JSPScKXopxcb+ugPKZvVLzr9/OfzA==}
peerDependencies:
'@codemirror/autocomplete': '>=6.0.0'
'@codemirror/commands': '>=6.0.0'
'@codemirror/language': '>=6.0.0'
'@codemirror/lint': '>=6.0.0'
'@codemirror/search': '>=6.0.0'
'@codemirror/state': '>=6.0.0'
'@codemirror/view': '>=6.0.0'
dependencies:
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
'@codemirror/commands': 6.1.3
'@codemirror/language': 6.3.2
'@codemirror/lint': 6.1.0
@@ -5952,14 +6006,11 @@ packages:
'@codemirror/view': 6.7.2
dev: false
/@uiw/react-codemirror/4.19.5_aguurb4bmecpxzejz52amioxne:
/@uiw/react-codemirror/4.19.5_k4ec5g7vuuzzonc3d6xbjnmmle:
resolution: {integrity: sha512-ZCHh8d7beXbF8/t7F1+yHht6A9Y6CdKeOkZq4A09lxJEnyTQrj1FMf2zvfaqc7K23KNjkTCtSlbqKKbVDgrWaw==}
peerDependencies:
'@babel/runtime': '>=7.11.0'
'@codemirror/state': '>=6.0.0'
'@codemirror/theme-one-dark': '>=6.0.0'
'@codemirror/view': '>=6.0.0'
codemirror: '>=6.0.0'
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
@@ -5968,14 +6019,13 @@ packages:
'@codemirror/state': 6.2.0
'@codemirror/theme-one-dark': 6.1.0
'@codemirror/view': 6.7.2
'@uiw/codemirror-extensions-basic-setup': 4.19.5_tbeldtdcrf45b35pezgkzq2u4e
codemirror: 6.0.1_@lezer+common@1.0.2
'@uiw/codemirror-extensions-basic-setup': 4.19.5_wd2tsis3in55bkaiwnc2c46tom
codemirror: 6.0.1
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
transitivePeerDependencies:
- '@codemirror/autocomplete'
- '@codemirror/language'
- '@codemirror/lint'
- '@codemirror/search'
dev: false
@@ -7286,18 +7336,16 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/codemirror/6.0.1_@lezer+common@1.0.2:
/codemirror/6.0.1:
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies:
'@codemirror/autocomplete': 6.4.0_eo6pz6bvsllvatnnwfprpuflde
'@codemirror/autocomplete': 6.4.0_czcfkg2f66rxeiodoti7r2gulu
'@codemirror/commands': 6.1.3
'@codemirror/language': 6.3.2
'@codemirror/lint': 6.1.0
'@codemirror/search': 6.2.3
'@codemirror/state': 6.2.0
'@codemirror/view': 6.7.2
transitivePeerDependencies:
- '@lezer/common'
dev: false
/collection-visit/1.0.0:
@@ -8633,7 +8681,7 @@ packages:
debug: 4.3.4
enhanced-resolve: 5.12.0
eslint: 8.31.0
eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq
eslint-plugin-import: 2.27.4_2ac3tknkazjoq5fxmuugu665ny
get-tsconfig: 4.3.0
globby: 13.1.3
is-core-module: 2.11.0
@@ -8643,7 +8691,7 @@ packages:
- supports-color
dev: true
/eslint-module-utils/2.7.4_sqt5xxn4ciiurbqrzlaarm6ama:
/eslint-module-utils/2.7.4_v73lhamtbyinynmwa5fn7kpmfq:
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
engines: {node: '>=4'}
peerDependencies:
@@ -8668,6 +8716,7 @@ packages:
debug: 3.2.7
eslint: 8.31.0
eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.3_hnftvkj7qg3s6bbigj4pr6djxy
transitivePeerDependencies:
- supports-color
dev: true
@@ -8692,7 +8741,7 @@ packages:
regexpp: 3.2.0
dev: true
/eslint-plugin-import/2.27.4_qdjeohovcytra7xto5vgmxssaq:
/eslint-plugin-import/2.27.4_2ac3tknkazjoq5fxmuugu665ny:
resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
engines: {node: '>=4'}
peerDependencies:
@@ -8710,7 +8759,7 @@ packages:
doctrine: 2.1.0
eslint: 8.31.0
eslint-import-resolver-node: 0.3.7
eslint-module-utils: 2.7.4_sqt5xxn4ciiurbqrzlaarm6ama
eslint-module-utils: 2.7.4_v73lhamtbyinynmwa5fn7kpmfq
has: 1.0.3
is-core-module: 2.11.0
is-glob: 4.0.3
@@ -13810,6 +13859,15 @@ packages:
shallow-equal: 1.2.1
dev: false
/react-dom/18.2.0:
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
react: ^18.2.0
dependencies:
loose-envify: 1.4.0
scheduler: 0.23.0
dev: false
/react-dom/18.2.0_react@18.2.0:
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
+1
View File
@@ -1,5 +1,6 @@
packages:
- "config-packages/*"
- "packages/*"
- "integrations/*"
- "apps/**"
- "examples/*"