Skip to content

Commit

Permalink
feat: schema validation
Browse files Browse the repository at this point in the history
  • Loading branch information
gentlementlegen committed Sep 23, 2024
1 parent 1208f25 commit aba3449
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 39 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
```
Expand Down Expand Up @@ -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.
- Run `yarn test` to run the tests.
36 changes: 36 additions & 0 deletions src/handlers/validator.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
51 changes: 16 additions & 35 deletions src/worker.ts
Original file line number Diff line number Diff line change
@@ -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<Response> {
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") {
Expand All @@ -29,42 +33,19 @@ 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);
}
},
};

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" } });
}

0 comments on commit aba3449

Please sign in to comment.