diff --git a/README.md b/README.md index cac1f27..62592af 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ To set up the `.dev.vars` file, you will need to provide the following variables ## Usage - Add the following to your `.ubiquibot-config.yml` file with the appropriate URL: -```javascript - -plugin: http://127.0.0.1:4000 - runsOn: [ "issue_comment.created", "issue_comment.edited", "issue_comment.deleted" , "issues.opened", "issues.edited", "issues.deleted"] +```yaml + - plugin: http://127.0.0.1:4000 + runsOn: [ "issue_comment.created", "issue_comment.edited", "issue_comment.deleted" , "issues.opened", "issues.edited", "issues.deleted"] ``` @@ -53,4 +53,4 @@ To set up the `.dev.vars` file, you will need to provide the following variables - Replace the placeholders with the appropriate values. ## Testing -- Run `yarn test` to run the tests. \ No newline at end of file +- Run `yarn test` to run the tests. diff --git a/src/handlers/validator.ts b/src/handlers/validator.ts new file mode 100644 index 0000000..6438455 --- /dev/null +++ b/src/handlers/validator.ts @@ -0,0 +1,36 @@ +import { TransformDecodeCheckError, TransformDecodeError, Value, ValueError } from "@sinclair/typebox/value"; +import { Env, envValidator, PluginSettings, pluginSettingsSchema, pluginSettingsValidator } from "../types"; + +export function validateAndDecodeSchemas(env: Env, rawSettings: object) { + const errors: ValueError[] = []; + const settings = Value.Default(pluginSettingsSchema, rawSettings) as PluginSettings; + + if (!pluginSettingsValidator.test(settings)) { + for (const error of pluginSettingsValidator.errors(settings)) { + console.error(error); + errors.push(error); + } + } + + if (!envValidator.test(env)) { + for (const error of envValidator.errors(env)) { + console.error(error); + errors.push(error); + } + } + + if (errors.length) { + throw { errors }; + } + + try { + const decodedEnv = Value.Decode(envValidator.schema, env); + const decodedSettings = Value.Decode(pluginSettingsSchema, settings); + return { decodedEnv, decodedSettings }; + } catch (e) { + if (e instanceof TransformDecodeCheckError || e instanceof TransformDecodeError) { + throw { errors: [e.error] }; + } + throw e; + } +} diff --git a/src/worker.ts b/src/worker.ts index 40df400..33370a1 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,17 +1,21 @@ -import { Value } from "@sinclair/typebox/value"; -import { plugin } from "./plugin"; -import { Env, envValidator, pluginSettingsSchema, pluginSettingsValidator } from "./types"; import manifest from "../manifest.json"; +import { validateAndDecodeSchemas } from "./handlers/validator"; +import { plugin } from "./plugin"; +import { Env } from "./types"; export default { async fetch(request: Request, env: Env): Promise { try { - if (request.method === "GET") { - const url = new URL(request.url); - if (url.pathname === "/manifest.json") { + const url = new URL(request.url); + if (url.pathname === "/manifest") { + if (request.method === "GET") { return new Response(JSON.stringify(manifest), { headers: { "content-type": "application/json" }, }); + } else if (request.method === "POST") { + const webhookPayload = await request.json(); + validateAndDecodeSchemas(env, webhookPayload.settings); + return new Response(JSON.stringify({ message: "Schema is valid" }), { status: 200, headers: { "content-type": "application/json" } }); } } if (request.method !== "POST") { @@ -29,33 +33,10 @@ export default { } const webhookPayload = await request.json(); - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); - - if (!pluginSettingsValidator.test(settings)) { - const errors: string[] = []; - for (const error of pluginSettingsValidator.errors(settings)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - return new Response(JSON.stringify({ error: `Error: "Invalid settings provided. ${errors.join("; ")}"` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - if (!envValidator.test(env)) { - const errors: string[] = []; - for (const error of envValidator.errors(env)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - return new Response(JSON.stringify({ error: `Error: "Invalid environment provided. ${errors.join("; ")}"` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } + const { decodedSettings, decodedEnv } = validateAndDecodeSchemas(env, webhookPayload.settings); - webhookPayload.settings = settings; - await plugin(webhookPayload, env); + webhookPayload.settings = decodedSettings; + await plugin(webhookPayload, decodedEnv); return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } }); } catch (error) { return handleUncaughtError(error); @@ -63,8 +44,8 @@ export default { }, }; -function handleUncaughtError(error: unknown) { - console.error(error); +function handleUncaughtError(errors: unknown) { + console.error(errors); const status = 500; - return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); + return new Response(JSON.stringify(errors), { status: status, headers: { "content-type": "application/json" } }); }