From 75c5a6278c3dcc800e67a59f267def00c93720a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Sat, 3 Feb 2024 16:30:04 +0900 Subject: [PATCH] refactor: organize into github directory the future vision of this kernel is to be able to handle webhook events from other platforms like telegram as well --- README.md | 5 ++-- package.json | 2 +- src/{octokit.ts => github/github-client.ts} | 0 src/{context.ts => github/github-context.ts} | 6 ++-- .../github-event-handler.ts} | 8 ++--- src/{ => github}/handlers/index.ts | 4 +-- .../handlers/issue/comment_created.ts | 4 +-- src/{ => github}/types/env.ts | 0 src/{ => github}/types/webhook-events.ts | 0 src/worker.ts | 30 +++++++++++-------- 10 files changed, 32 insertions(+), 27 deletions(-) rename src/{octokit.ts => github/github-client.ts} (100%) rename src/{context.ts => github/github-context.ts} (76%) rename src/{event-handler.ts => github/github-event-handler.ts} (87%) rename src/{ => github}/handlers/index.ts (53%) rename src/{ => github}/handlers/issue/comment_created.ts (68%) rename src/{ => github}/types/env.ts (100%) rename src/{ => github}/types/webhook-events.ts (100%) diff --git a/README.md b/README.md index 5877e21..02de68b 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ The kernel is designed to: You need to obtain a private key from your GitHub App settings and convert it to Public-Key Cryptography Standards #8 (PKCS#8) format. You can use the following command to perform this conversion and append the result to your `.dev.vars` file: ```sh - echo "PRIVATE_KEY=\"$(openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in YOUR_PRIVATE_KEY.PEM | awk 'BEGIN{ORS="\\n"} 1')\"" >> .dev.vars - ``` + echo "PRIVATE_KEY=\"$(openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in YOUR_PRIVATE_KEY.PEM | awk 'BEGIN{ORS="\\n"} 1')\"" >> .dev.vars + ``` + ###### Please replace `YOUR_PRIVATE_KEY.PEM` with the path to your actual PEM file when running the command. - `WEBHOOK_SECRET` diff --git a/package.json b/package.json index 850704a..979971c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "dev": "run-p worker proxy", - "predev": "lsof -i tcp:8787 | grep LISTEN | awk '{print $2}' | xargs kill -9", + "predev": "lsof -i tcp:8787 | grep LISTEN | awk '{print $2}' | xargs kill -9", "format": "run-s format:lint format:prettier format:cspell", "format:lint": "eslint --fix .", "format:prettier": "prettier --write .", diff --git a/src/octokit.ts b/src/github/github-client.ts similarity index 100% rename from src/octokit.ts rename to src/github/github-client.ts diff --git a/src/context.ts b/src/github/github-context.ts similarity index 76% rename from src/context.ts rename to src/github/github-context.ts index 0d7fe61..f5157ec 100644 --- a/src/context.ts +++ b/src/github/github-context.ts @@ -1,7 +1,7 @@ import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks"; -import { customOctokit } from "./octokit"; +import { customOctokit } from "./github-client"; -export class Context { +export class GitHubContext { public key: WebhookEventName; public name: WebhookEventName; public id: string; @@ -21,4 +21,4 @@ export class Context { } } -export type SimplifiedContext = Omit; +export type SimplifiedContext = Omit; diff --git a/src/event-handler.ts b/src/github/github-event-handler.ts similarity index 87% rename from src/event-handler.ts rename to src/github/github-event-handler.ts index 39a6802..fbbb2d5 100644 --- a/src/event-handler.ts +++ b/src/github/github-event-handler.ts @@ -1,6 +1,6 @@ import { Webhooks } from "@octokit/webhooks"; -import { Context, SimplifiedContext } from "./context"; -import { customOctokit } from "./octokit"; +import { customOctokit } from "./github-client"; +import { GitHubContext, SimplifiedContext } from "./github-context"; export type Options = { webhookSecret: string; @@ -8,7 +8,7 @@ export type Options = { privateKey: string; }; -export class EventHandler { +export class GitHubEventHandler { public webhooks: Webhooks; public on: Webhooks["on"]; public onAny: Webhooks["onAny"]; @@ -38,7 +38,7 @@ export class EventHandler { }, }); - return new Context(event, octokit); + return new GitHubContext(event, octokit); }, }); diff --git a/src/handlers/index.ts b/src/github/handlers/index.ts similarity index 53% rename from src/handlers/index.ts rename to src/github/handlers/index.ts index f98e21f..7740436 100644 --- a/src/handlers/index.ts +++ b/src/github/handlers/index.ts @@ -1,6 +1,6 @@ -import { EventHandler } from "../event-handler"; +import { GitHubEventHandler } from "../github-event-handler"; import { handleIssueCommentCreated } from "./issue/comment_created"; -export function bindHandlers(webhooks: EventHandler) { +export function bindHandlers(webhooks: GitHubEventHandler) { webhooks.on("issue_comment.created", handleIssueCommentCreated); } diff --git a/src/handlers/issue/comment_created.ts b/src/github/handlers/issue/comment_created.ts similarity index 68% rename from src/handlers/issue/comment_created.ts rename to src/github/handlers/issue/comment_created.ts index 82d2e8d..2ccf4ea 100644 --- a/src/handlers/issue/comment_created.ts +++ b/src/github/handlers/issue/comment_created.ts @@ -1,6 +1,6 @@ -import { Context } from "../../context"; +import { GitHubContext } from "../../github-context"; -export async function handleIssueCommentCreated(event: Context<"issue_comment.created">) { +export async function handleIssueCommentCreated(event: GitHubContext<"issue_comment.created">) { if (event.payload.comment.user.type === "Bot") { console.log("Skipping bot comment"); return; diff --git a/src/types/env.ts b/src/github/types/env.ts similarity index 100% rename from src/types/env.ts rename to src/github/types/env.ts diff --git a/src/types/webhook-events.ts b/src/github/types/webhook-events.ts similarity index 100% rename from src/types/webhook-events.ts rename to src/github/types/webhook-events.ts diff --git a/src/worker.ts b/src/worker.ts index a88dff5..4b8cf8b 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,8 +1,8 @@ import { EmitterWebhookEventName as WebhookEventName, emitterEventNames } from "@octokit/webhooks"; import { Value } from "@sinclair/typebox/value"; -import { EventHandler } from "./event-handler"; -import { bindHandlers } from "./handlers"; -import { Env, envSchema } from "./types/env"; +import { GitHubEventHandler } from "./github/github-event-handler"; +import { bindHandlers } from "./github/handlers"; +import { Env, envSchema } from "./github/types/env"; export default { async fetch(request: Request, env: Env): Promise { try { @@ -10,23 +10,27 @@ export default { const eventName = getEventName(request); const signatureSHA256 = getSignature(request); const id = getId(request); - const eventHandler = new EventHandler({ webhookSecret: env.WEBHOOK_SECRET, appId: env.APP_ID, privateKey: env.PRIVATE_KEY }); + const eventHandler = new GitHubEventHandler({ webhookSecret: env.WEBHOOK_SECRET, appId: env.APP_ID, privateKey: env.PRIVATE_KEY }); bindHandlers(eventHandler); await eventHandler.webhooks.verifyAndReceive({ id, name: eventName, payload: await request.text(), signature: signatureSHA256 }); return new Response("ok\n", { status: 200, headers: { "content-type": "text/plain" } }); } catch (error) { - console.error(error); - let status = 500; - let errorMessage = "An unspecified error occurred"; - if (error instanceof AggregateError) { - const err = error.errors[0]; - errorMessage = err.message ? `${err.name}: ${err.message}` : "Error: An unspecified error occurred"; - status = typeof err.status !== "undefined" ? err.status : 500; - } - return new Response(JSON.stringify({ error: errorMessage }), { status: status, headers: { "content-type": "application/json" } }); + return handleUncaughtError(error); } }, }; +function handleUncaughtError(error: unknown) { + console.error(error); + let status = 500; + let errorMessage = "An uncaught error occurred"; + if (error instanceof AggregateError) { + const err = error.errors[0]; + errorMessage = err.message ? `${err.name}: ${err.message}` : `Error: ${errorMessage}`; + status = typeof err.status !== "undefined" ? err.status : 500; + } + return new Response(JSON.stringify({ error: errorMessage }), { status: status, headers: { "content-type": "application/json" } }); +} + function validateEnv(env: Env): void { if (!Value.Check(envSchema, env)) { const errors = [...Value.Errors(envSchema, env)];