From ca34b57f1e44e57616d7228aadc2b62db9e43940 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:33:10 +0900 Subject: [PATCH 01/22] refactor: update Context type and enhance plugin structure Replaces `Context` with `ContextPlugin` in multiple files to utilize standardized context structure. --- package.json | 6 +- src/adapters/index.ts | 4 +- .../supabase/helpers/tables/access.ts | 2 +- src/adapters/supabase/helpers/tables/label.ts | 2 +- src/adapters/supabase/helpers/tables/super.ts | 2 +- src/adapters/supabase/helpers/tables/user.ts | 2 +- src/handlers/comment.ts | 9 +- src/handlers/handle-parent-issue.ts | 4 +- src/handlers/label-change.ts | 6 +- src/handlers/pricing-label.ts | 24 +- src/handlers/sync-labels-to-config.ts | 4 +- src/index.ts | 50 ++- src/run.ts | 42 +-- src/shared/issue.ts | 14 +- src/shared/label.ts | 28 +- src/shared/permissions.ts | 4 +- src/shared/pricing.ts | 8 +- src/types/plugin-input.ts | 7 +- src/types/typeguards.ts | 9 +- src/worker.ts | 91 ++--- tests/main.test.ts | 8 +- yarn.lock | 311 +++++++++++++++++- 22 files changed, 421 insertions(+), 216 deletions(-) diff --git a/package.json b/package.json index 52cb6b2..a25a4d4 100644 --- a/package.json +++ b/package.json @@ -35,12 +35,12 @@ "@commander-js/extra-typings": "12.0.1", "@octokit/rest": "^20.0.2", "@octokit/webhooks": "^13.1.0", - "@sinclair/typebox": "^0.32.15", + "@sinclair/typebox": "^0.33.17", "@supabase/supabase-js": "2.43.1", + "@ubiquity-os/ubiquity-os-kernel": "^2.5.1", "commander": "12.0.0", "decimal.js": "^10.4.3", - "dotenv": "^16.4.5", - "typebox-validators": "0.3.5" + "dotenv": "^16.4.5" }, "devDependencies": { "@commitlint/cli": "^18.6.1", diff --git a/src/adapters/index.ts b/src/adapters/index.ts index ef7d6c9..941ac2c 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1,9 +1,9 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Access } from "./supabase/helpers/tables/access"; -import { User } from "./supabase/helpers/tables/user"; import { Label } from "./supabase/helpers/tables/label"; import { Super } from "./supabase/helpers/tables/super"; +import { User } from "./supabase/helpers/tables/user"; export function createAdapters(supabaseClient: SupabaseClient, context: Context) { return { diff --git a/src/adapters/supabase/helpers/tables/access.ts b/src/adapters/supabase/helpers/tables/access.ts index 6269fea..650c7af 100644 --- a/src/adapters/supabase/helpers/tables/access.ts +++ b/src/adapters/supabase/helpers/tables/access.ts @@ -1,5 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../../../../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; import { Super } from "./super"; diff --git a/src/adapters/supabase/helpers/tables/label.ts b/src/adapters/supabase/helpers/tables/label.ts index a5f48ee..6239e94 100644 --- a/src/adapters/supabase/helpers/tables/label.ts +++ b/src/adapters/supabase/helpers/tables/label.ts @@ -1,8 +1,8 @@ import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; import { Super } from "./super"; -import { Context } from "../../../../types/context"; type LabelRow = Database["public"]["Tables"]["labels"]["Row"]; diff --git a/src/adapters/supabase/helpers/tables/super.ts b/src/adapters/supabase/helpers/tables/super.ts index 662fb69..9bbaf81 100644 --- a/src/adapters/supabase/helpers/tables/super.ts +++ b/src/adapters/supabase/helpers/tables/super.ts @@ -1,5 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../../../../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; export class Super { diff --git a/src/adapters/supabase/helpers/tables/user.ts b/src/adapters/supabase/helpers/tables/user.ts index b41130f..a4f52e2 100644 --- a/src/adapters/supabase/helpers/tables/user.ts +++ b/src/adapters/supabase/helpers/tables/user.ts @@ -1,6 +1,6 @@ import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Super } from "./super"; -import { Context } from "../../../../types/context"; export class User extends Super { constructor(supabase: SupabaseClient, context: Context) { diff --git a/src/handlers/comment.ts b/src/handlers/comment.ts index 40cef62..c1827d9 100644 --- a/src/handlers/comment.ts +++ b/src/handlers/comment.ts @@ -1,13 +1,14 @@ import { addCommentToIssue, isUserAdminOrBillingManager } from "../shared/issue"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { isCommentEvent } from "../types/typeguards"; import commandParser, { AllowedCommand, CommandArguments, isValidCommand } from "./command-parser"; -const commandHandlers: { [k in AllowedCommand]: (context: Context, commandArguments: CommandArguments) => Promise } = { +const commandHandlers: { [k in AllowedCommand]: (context: ContextPlugin, commandArguments: CommandArguments) => Promise } = { async allow(context, { username, labels }: CommandArguments) { const logger = context.logger; if (!isCommentEvent(context)) { - return logger.debug("Not an comment event"); + logger.debug("Not an comment event"); + return; } const payload = context.payload; const sender = payload.sender.login; @@ -24,7 +25,7 @@ const commandHandlers: { [k in AllowedCommand]: (context: Context, commandArgume }, }; -export async function handleComment(context: Context) { +export async function handleComment(context: ContextPlugin) { const logger = context.logger; if (!isCommentEvent(context)) { return logger.debug("Not an comment event"); diff --git a/src/handlers/handle-parent-issue.ts b/src/handlers/handle-parent-issue.ts index 7fb2ff3..8e6dee9 100644 --- a/src/handlers/handle-parent-issue.ts +++ b/src/handlers/handle-parent-issue.ts @@ -1,9 +1,9 @@ import { clearAllPriceLabelsOnIssue } from "../shared/label"; import { calculateLabelValue } from "../shared/pricing"; -import { Context } from "../types/context"; import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; -export async function handleParentIssue(context: Context, labels: Label[]) { +export async function handleParentIssue(context: ContextPlugin, labels: Label[]) { const issuePrices = labels.filter((label) => label.name.toString().startsWith("Price:")); if (issuePrices.length) { await clearAllPriceLabelsOnIssue(context); diff --git a/src/handlers/label-change.ts b/src/handlers/label-change.ts index 48275d2..010ee26 100644 --- a/src/handlers/label-change.ts +++ b/src/handlers/label-change.ts @@ -1,8 +1,8 @@ import { isUserAdminOrBillingManager } from "../shared/issue"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { isLabelEditedEvent } from "../types/typeguards"; -export async function watchLabelChange(context: Context) { +export async function watchLabelChange(context: ContextPlugin) { const logger = context.logger; if (!isLabelEditedEvent(context)) { logger.debug("Not a label event"); @@ -38,7 +38,7 @@ export async function watchLabelChange(context: Context) { return logger.debug("label name change saved to db"); } -async function hasLabelEditPermission(context: Context, label: string, caller: string) { +async function hasLabelEditPermission(context: ContextPlugin, label: string, caller: string) { const sufficientPrivileges = await isUserAdminOrBillingManager(context, caller); // get text before : diff --git a/src/handlers/pricing-label.ts b/src/handlers/pricing-label.ts index 1d6cff6..21cbe31 100644 --- a/src/handlers/pricing-label.ts +++ b/src/handlers/pricing-label.ts @@ -1,14 +1,12 @@ -import { Context } from "../types/context"; - import { addLabelToIssue, clearAllPriceLabelsOnIssue, createLabel, listLabelsForRepo, removeLabelFromIssue } from "../shared/label"; import { labelAccessPermissionsCheck } from "../shared/permissions"; import { setPrice } from "../shared/pricing"; import { Label, UserType } from "../types/github"; -import { AssistivePricingSettings } from "../types/plugin-input"; +import { AssistivePricingSettings, ContextPlugin } from "../types/plugin-input"; import { isIssueLabelEvent } from "../types/typeguards"; import { handleParentIssue, isParentIssue, sortLabelsByValue } from "./handle-parent-issue"; -export async function onLabelChangeSetPricing(context: Context): Promise { +export async function onLabelChangeSetPricing(context: ContextPlugin): Promise { if (!isIssueLabelEvent(context)) { context.logger.debug("Not an issue event"); return; @@ -46,7 +44,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const smallestPriceLabelName = smallestPriceLabel?.name; if (smallestPriceLabelName) { for (const label of sortedPriceLabels) { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, @@ -61,7 +59,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { await setPriceLabel(context, labels, config); } -async function setPriceLabel(context: Context, issueLabels: Label[], config: AssistivePricingSettings) { +async function setPriceLabel(context: ContextPlugin, issueLabels: Label[], config: AssistivePricingSettings) { const logger = context.logger; const labelNames = issueLabels.map((i) => i.name); @@ -121,7 +119,7 @@ function getMinLabels(recognizedLabels: { time: Label[]; priority: Label[] }) { return { time: minTimeLabel, priority: minPriorityLabel }; } -async function handleTargetPriceLabel(context: Context, targetPriceLabel: string, labelNames: string[]) { +async function handleTargetPriceLabel(context: ContextPlugin, targetPriceLabel: string, labelNames: string[]) { const _targetPriceLabel = labelNames.find((name) => name.includes("Price") && name.includes(targetPriceLabel)); if (_targetPriceLabel) { @@ -135,7 +133,7 @@ async function handleTargetPriceLabel(context: Context, targetPriceLabel: string } } -async function handleExistingPriceLabel(context: Context, targetPriceLabel: string) { +async function handleExistingPriceLabel(context: ContextPlugin, targetPriceLabel: string) { const logger = context.logger; let labeledEvents = await getAllLabeledEvents(context); if (!labeledEvents) return logger.error("No labeled events found"); @@ -150,32 +148,32 @@ async function handleExistingPriceLabel(context: Context, targetPriceLabel: stri } } -async function addPriceLabelToIssue(context: Context, targetPriceLabel: string) { +async function addPriceLabelToIssue(context: ContextPlugin, targetPriceLabel: string) { await clearAllPriceLabelsOnIssue(context); await addLabelToIssue(context, targetPriceLabel); } -async function getAllLabeledEvents(context: Context) { +async function getAllLabeledEvents(context: ContextPlugin) { const events = await getAllIssueEvents(context); if (!events) return null; return events.filter((event) => event.event === "labeled"); } -async function getAllIssueEvents(context: Context) { +async function getAllIssueEvents(context: ContextPlugin) { if (!("issue" in context.payload) || !context.payload.issue) { context.logger.debug("Not an issue event"); return; } try { - return await context.octokit.paginate(context.octokit.issues.listEvents, { + return await context.octokit.paginate(context.octokit.rest.issues.listEvents, { owner: context.payload.repository.owner.login, repo: context.payload.repository.name, issue_number: context.payload.issue.number, per_page: 100, }); } catch (err: unknown) { - context.logger.error("Failed to fetch lists of events", err); + context.logger.error("Failed to fetch lists of events", { err }); return []; } } diff --git a/src/handlers/sync-labels-to-config.ts b/src/handlers/sync-labels-to-config.ts index a256048..3975206 100644 --- a/src/handlers/sync-labels-to-config.ts +++ b/src/handlers/sync-labels-to-config.ts @@ -1,11 +1,11 @@ import { createLabel, listLabelsForRepo } from "../shared/label"; import { calculateLabelValue, calculateTaskPrice } from "../shared/pricing"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; // This just checks all the labels in the config have been set in gh issue // If there's something missing, they will be added -export async function syncPriceLabelsToConfig(context: Context) { +export async function syncPriceLabelsToConfig(context: ContextPlugin) { const config = context.config; const logger = context.logger; diff --git a/src/index.ts b/src/index.ts index 550e3a3..80fd386 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,33 +1,21 @@ -import * as github from "@actions/github"; -import * as core from "@actions/core"; -import { Value } from "@sinclair/typebox/value"; -import { envSchema } from "./types/env"; -import { pluginSettingsSchema, PluginInputs } from "./types/plugin-input"; +import { createClient } from "@supabase/supabase-js"; +import { createActionsPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import { LogLevel } from "@ubiquity-os/ubiquity-os-logger"; +import { createAdapters } from "./adapters"; import { run } from "./run"; +import { SupportedEvents } from "./types/context"; +import { Env, envSchema } from "./types/env"; +import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; -/** - * Run the plugin as a GitHub Action instance. - */ -async function actionRun() { - const env = Value.Decode(envSchema, process.env); - - const webhookPayload = github.context.payload.inputs; - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(webhookPayload.settings))); - - const inputs: PluginInputs = { - stateId: webhookPayload.stateId, - eventName: webhookPayload.eventName, - eventPayload: JSON.parse(webhookPayload.eventPayload), - settings: settings, - authToken: webhookPayload.authToken, - ref: webhookPayload.ref, - }; - await run(inputs, env); -} - -actionRun() - .then((result) => core.setOutput("result", result)) - .catch((error) => { - console.error(error); - core.setFailed(error); - }); +createActionsPlugin( + (context) => { + return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); + }, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: process.env.LOG_LEVEL as LogLevel, + kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, + } +).catch(console.error); diff --git a/src/run.ts b/src/run.ts index 77ab139..472ed3e 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,45 +1,12 @@ -import { Octokit } from "@octokit/rest"; -import { createClient } from "@supabase/supabase-js"; -import { createAdapters } from "./adapters"; import { handleComment } from "./handlers/comment"; import { watchLabelChange } from "./handlers/label-change"; import { onLabelChangeSetPricing } from "./handlers/pricing-label"; import { syncPriceLabelsToConfig } from "./handlers/sync-labels-to-config"; -import { Context } from "./types/context"; -import { Env } from "./types/env"; -import { PluginInputs } from "./types/plugin-input"; +import { ContextPlugin } from "./types/plugin-input"; -export async function run(inputs: PluginInputs, env: Env) { - const octokit = new Octokit({ auth: inputs.authToken }); - const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); +export async function run(context: ContextPlugin) { + const { eventName, logger } = context; - const context: Context = { - eventName: inputs.eventName, - payload: inputs.eventPayload, - config: inputs.settings, - octokit, - logger: { - debug(message: unknown, ...optionalParams: unknown[]) { - console.debug(message, ...optionalParams); - }, - info(message: unknown, ...optionalParams: unknown[]) { - console.log(message, ...optionalParams); - }, - warn(message: unknown, ...optionalParams: unknown[]) { - console.warn(message, ...optionalParams); - }, - error(message: unknown, ...optionalParams: unknown[]) { - console.error(message, ...optionalParams); - }, - fatal(message: unknown, ...optionalParams: unknown[]) { - console.error(message, ...optionalParams); - }, - }, - adapters: {} as ReturnType, - }; - context.adapters = createAdapters(supabaseClient, context); - - const eventName = inputs.eventName; switch (eventName) { case "issues.opened": case "repository.created": @@ -57,6 +24,7 @@ export async function run(inputs: PluginInputs, env: Env) { await handleComment(context); break; default: - context.logger.warn(`Event ${eventName} is not supported`); + logger.error(`Event ${eventName} is not supported`); } + return { message: "OK" }; } diff --git a/src/shared/issue.ts b/src/shared/issue.ts index 35b308d..89cceb5 100644 --- a/src/shared/issue.ts +++ b/src/shared/issue.ts @@ -1,6 +1,6 @@ -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; -async function checkIfIsAdmin(context: Context, username: string) { +async function checkIfIsAdmin(context: ContextPlugin, username: string) { const response = await context.octokit.rest.repos.getCollaboratorPermissionLevel({ owner: context.payload.repository.owner.login, repo: context.payload.repository.name, @@ -9,7 +9,7 @@ async function checkIfIsAdmin(context: Context, username: string) { return response.data.permission === "admin"; } -async function checkIfIsBillingManager(context: Context, username: string) { +async function checkIfIsBillingManager(context: ContextPlugin, username: string) { if (!context.payload.organization) throw context.logger.error(`No organization found in payload!`); try { @@ -28,7 +28,7 @@ async function checkIfIsBillingManager(context: Context, username: string) { return membership.role === "billing_manager"; } -export async function isUserAdminOrBillingManager(context: Context, username: string): Promise<"admin" | "billing_manager" | false> { +export async function isUserAdminOrBillingManager(context: ContextPlugin, username: string): Promise<"admin" | "billing_manager" | false> { const isAdmin = await checkIfIsAdmin(context, username); if (isAdmin) return "admin"; @@ -38,16 +38,16 @@ export async function isUserAdminOrBillingManager(context: Context, username: st return false; } -export async function addCommentToIssue(context: Context, message: string, issueNumber: number, owner?: string, repo?: string) { +export async function addCommentToIssue(context: ContextPlugin, message: string, issueNumber: number, owner?: string, repo?: string) { const payload = context.payload; try { - await context.octokit.issues.createComment({ + await context.octokit.rest.issues.createComment({ owner: owner ?? payload.repository.owner.login, repo: repo ?? payload.repository.name, issue_number: issueNumber, body: message, }); } catch (e: unknown) { - context.logger.error("Adding a comment failed!", e); + context.logger.error("Adding a comment failed!", { e }); } } diff --git a/src/shared/label.ts b/src/shared/label.ts index 179273f..0842eab 100644 --- a/src/shared/label.ts +++ b/src/shared/label.ts @@ -1,11 +1,11 @@ -import { Context } from "../types/context"; import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; // cspell:disable const COLORS = { default: "ededed", price: "1f883d" }; // cspell:enable -export async function listLabelsForRepo(context: Context): Promise { +export async function listLabelsForRepo(context: ContextPlugin): Promise { const payload = context.payload; const res = await context.octokit.rest.issues.listLabelsForRepo({ @@ -21,7 +21,7 @@ export async function listLabelsForRepo(context: Context): Promise { throw context.logger.error("Failed to fetch lists of labels", { status: res.status }); } -export async function createLabel(context: Context, name: string, labelType = "default" as keyof typeof COLORS): Promise { +export async function createLabel(context: ContextPlugin, name: string, labelType = "default" as keyof typeof COLORS): Promise { const payload = context.payload; const color = name.startsWith("Price: ") ? COLORS.price : COLORS[labelType]; @@ -34,7 +34,7 @@ export async function createLabel(context: Context, name: string, labelType = "d }); } -export async function clearAllPriceLabelsOnIssue(context: Context) { +export async function clearAllPriceLabelsOnIssue(context: ContextPlugin) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; @@ -47,25 +47,25 @@ export async function clearAllPriceLabelsOnIssue(context: Context) { for (const label of issuePriceLabels) { try { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, name: label.name, }); } catch (e: unknown) { - context.logger.error("Clearing all price labels failed!", e); + context.logger.error("Clearing all price labels failed!", { e }); } } } -export async function addLabelToIssue(context: Context, labelName: string) { +export async function addLabelToIssue(context: ContextPlugin, labelName: string) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; } try { - await context.octokit.issues.addLabels({ + await context.octokit.rest.issues.addLabels({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, @@ -77,29 +77,29 @@ export async function addLabelToIssue(context: Context, labelName: string) { await updateLabelColor(context, labelName, COLORS.price); } } catch (e: unknown) { - context.logger.error("Adding a label to issue failed!", e); + context.logger.error("Adding a label to issue failed!", { e }); } } -export async function removeLabelFromIssue(context: Context, labelName: string) { +export async function removeLabelFromIssue(context: ContextPlugin, labelName: string) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; } try { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, name: labelName, }); } catch (e: unknown) { - context.logger.error("Adding a label to issue failed!", e); + context.logger.error("Adding a label to issue failed!", { e }); } } -async function updateLabelColor(context: Context, labelName: string, color: string) { +async function updateLabelColor(context: ContextPlugin, labelName: string, color: string) { const payload = context.payload; try { await context.octokit.rest.issues.updateLabel({ @@ -109,6 +109,6 @@ async function updateLabelColor(context: Context, labelName: string, color: stri color, }); } catch (e: unknown) { - context.logger.error("Updating label color failed!", e); + context.logger.error("Updating label color failed!", { e }); } } diff --git a/src/shared/permissions.ts b/src/shared/permissions.ts index 0a39e1f..4ee4e3f 100644 --- a/src/shared/permissions.ts +++ b/src/shared/permissions.ts @@ -1,10 +1,10 @@ -import { Context } from "../types/context"; import { UserType } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; import { isIssueLabelEvent } from "../types/typeguards"; import { addCommentToIssue, isUserAdminOrBillingManager } from "./issue"; import { addLabelToIssue, removeLabelFromIssue } from "./label"; -export async function labelAccessPermissionsCheck(context: Context) { +export async function labelAccessPermissionsCheck(context: ContextPlugin) { if (!isIssueLabelEvent(context)) { context.logger.debug("Not an issue event"); return; diff --git a/src/shared/pricing.ts b/src/shared/pricing.ts index 3b0980d..fac82fa 100644 --- a/src/shared/pricing.ts +++ b/src/shared/pricing.ts @@ -1,14 +1,14 @@ -import { Context } from "../types/context"; -import { Label } from "../types/github"; import { Decimal } from "decimal.js"; +import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; -export function calculateTaskPrice(context: Context, timeValue: number, priorityValue: number, baseValue?: number): string { +export function calculateTaskPrice(context: ContextPlugin, timeValue: number, priorityValue: number, baseValue?: number): string { const base = baseValue ?? context.config.basePriceMultiplier; const priority = new Decimal(priorityValue).div(10); // floats cause bad math return new Decimal(base).mul(1000).mul(timeValue).mul(priority).toDecimalPlaces(2).toString(); } -export function setPrice(context: Context, timeLabel: Label, priorityLabel: Label) { +export function setPrice(context: ContextPlugin, timeLabel: Label, priorityLabel: Label) { const logger = context.logger; const { labels } = context.config; diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index e5c6e46..9833e50 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -1,7 +1,10 @@ import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks"; +import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { StandardValidator } from "typebox-validators"; +import { createAdapters } from "../adapters"; import { SupportedEvents } from "./context"; -import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { Env } from "./env"; export interface PluginInputs { stateId: string; @@ -36,3 +39,5 @@ export const pluginSettingsSchema = T.Object( export const assistivePricingSchemaValidator = new StandardValidator(pluginSettingsSchema); export type AssistivePricingSettings = StaticDecode; + +export type ContextPlugin = Context & { adapters: ReturnType }; diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index f21cddc..2b62724 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,12 +1,13 @@ import { Context } from "./context"; +import { ContextPlugin } from "./plugin-input"; export function isCommentEvent( - context: Context -): context is Context & { payload: { issue: Context<"issue_comment">["payload"]["issue"]; comment: Context<"issue_comment">["payload"]["comment"] } } { + context: ContextPlugin +): context is ContextPlugin & { payload: { issue: Context<"issue_comment">["payload"]["issue"]; comment: Context<"issue_comment">["payload"]["comment"] } } { return context.eventName.startsWith("issue_comment."); } -export function isIssueLabelEvent(context: Context): context is Context & { +export function isIssueLabelEvent(context: ContextPlugin): context is ContextPlugin & { payload: { issue: Context<"issues.labeled" | "issues.unlabeled">["payload"]["issue"]; label: Context<"issues.labeled" | "issues.unlabeled">["payload"]["label"]; @@ -15,7 +16,7 @@ export function isIssueLabelEvent(context: Context): context is Context & { return context.eventName === "issues.labeled" || context.eventName === "issues.unlabeled"; } -export function isLabelEditedEvent(context: Context): context is Context & { +export function isLabelEditedEvent(context: ContextPlugin): context is ContextPlugin & { payload: { label: Context<"label.edited">["payload"]["label"]; changes: Context<"label.edited">["payload"]["changes"]; diff --git a/src/worker.ts b/src/worker.ts index 2377ed1..3852a86 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,74 +1,23 @@ -import manifest from "../manifest.json"; -import { validateAndDecodeSchemas } from "./handlers/validator"; +import { createClient } from "@supabase/supabase-js"; +import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import { createAdapters } from "./adapters"; import { run } from "./run"; -import { Env } from "./types/env"; - -export default { - async fetch(request: Request, env: Env): Promise { - try { - const url = new URL(request.url); - if (url.pathname === "/manifest.json" && request.method === "GET") { - return new Response(JSON.stringify(manifest), { - headers: { "content-type": "application/json" }, - }); - } - if (request.method !== "POST") { - return new Response(JSON.stringify({ error: `Only POST requests are supported.` }), { - status: 405, - headers: { "content-type": "application/json", Allow: "POST" }, - }); - } - const contentType = request.headers.get("content-type"); - if (contentType !== "application/json") { - return new Response(JSON.stringify({ error: `Bad request: ${contentType} is not a valid content type` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - const webhookPayload = await request.json(); - // TODO: temporarily disabled, should be added back with the proper key in the configuration. - // const signature = webhookPayload.signature; - // delete webhookPayload.signature; - // if (!(await verifySignature(env.UBIQUIBOT_PUBLIC_KEY, webhookPayload, signature))) { - // return new Response(JSON.stringify({ error: `Forbidden: Signature verification failed` }), { - // status: 403, - // headers: { "content-type": "application/json" }, - // }); - // } - const result = validateAndDecodeSchemas(env, webhookPayload.settings); +import { SupportedEvents } from "./types/context"; +import { Env, envSchema } from "./types/env"; +import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; +import manifest from "../manifest.json"; - webhookPayload.settings = result.decodedSettings; - await run(webhookPayload, result.decodedEnv); - return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } }); - } catch (error) { - return handleUncaughtError(error); - } +export default createPlugin( + (context) => { + return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); }, -}; - -function handleUncaughtError(errors: unknown) { - console.error(errors); - const status = 500; - return new Response(JSON.stringify(errors), { status: status, headers: { "content-type": "application/json" } }); -} - -// async function verifySignature(publicKeyPem: string, payload: unknown, signature: string) { -// const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").trim(); -// const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0)); -// -// const publicKey = await crypto.subtle.importKey( -// "spki", -// binaryDer.buffer, -// { -// name: "RSASSA-PKCS1-v1_5", -// hash: "SHA-256", -// }, -// true, -// ["verify"] -// ); -// -// const signatureArray = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0)); -// const dataArray = new TextEncoder().encode(JSON.stringify(payload)); -// -// return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, signatureArray, dataArray); -// } + //@ts-expect-error types are ok + manifest, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: process.env.LOG_LEVEL, + kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, + } +); diff --git a/tests/main.test.ts b/tests/main.test.ts index f5dc6e9..5bb21f0 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -1,15 +1,15 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; import { drop } from "@mswjs/data"; +import * as crypto from "crypto"; import commandParser, { CommandArguments } from "../src/handlers/command-parser"; +import { calculateLabelValue, calculateTaskPrice } from "../src/shared/pricing"; import { Env } from "../src/types/env"; +import { ContextPlugin } from "../src/types/plugin-input"; import workerFetch from "../src/worker"; import { db } from "./__mocks__/db"; import { server } from "./__mocks__/node"; import issueCommented from "./__mocks__/requests/issue-comment-post.json"; import usersGet from "./__mocks__/users-get.json"; -import * as crypto from "crypto"; -import { calculateLabelValue, calculateTaskPrice } from "../src/shared/pricing"; -import { Context } from "../src/types/context"; const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048, @@ -123,7 +123,7 @@ describe("User tests", () => { }, ]; for (const testCase of testCases) { - const price = calculateTaskPrice(context as unknown as Context, testCase.timeValue, testCase.priorityValue); + const price = calculateTaskPrice(context as unknown as ContextPlugin, testCase.timeValue, testCase.priorityValue); expect(price).toEqual(testCase.expectedPrice); } }); diff --git a/yarn.lock b/yarn.lock index 47d9bed..1882185 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@actions/core@^1.10.1": +"@actions/core@1.10.1", "@actions/core@^1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a" integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g== @@ -15,7 +15,7 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" -"@actions/github@^6.0.0": +"@actions/github@6.0.0", "@actions/github@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.0.tgz#65883433f9d81521b782a64cc1fd45eef2191ea7" integrity sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g== @@ -349,6 +349,11 @@ dependencies: statuses "^2.0.1" +"@cfworker/json-schema@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@cfworker/json-schema/-/json-schema-2.0.1.tgz#563463393a1f19b06732491e604e0cc8255baf8a" + integrity sha512-1w7xVrTFjAWBVaOWRH5AMdKpJdltF4iy/d93E7qj8Rox6yY9OzEW1aC7T5eONrDOxXrlnsclPw9v24XW2c0mkg== + "@cloudflare/kv-asset-handler@0.3.4": version "0.3.4" resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz#5cc152847c8ae4d280ec5d7f4f6ba8c976b585c3" @@ -1649,11 +1654,75 @@ dependencies: which "^4.0.0" +"@octokit/auth-app@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-7.1.0.tgz#55a3d3b3b3607b9d375abbe946163dca3a25c2c9" + integrity sha512-cazGaJPSgeZ8NkVYeM/C5l/6IQ5vZnsI8p1aMucadCkt/bndI+q+VqwrlnWbASRmenjOkf1t1RpCKrif53U8gw== + dependencies: + "@octokit/auth-oauth-app" "^8.1.0" + "@octokit/auth-oauth-user" "^5.1.0" + "@octokit/request" "^9.1.1" + "@octokit/request-error" "^6.1.1" + "@octokit/types" "^13.4.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^2.2.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-app@^8.1.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.1.tgz#6204affa6e86f535016799cadf2af9befe5e893c" + integrity sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg== + dependencies: + "@octokit/auth-oauth-device" "^7.0.0" + "@octokit/auth-oauth-user" "^5.0.1" + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-device@^7.0.0", "@octokit/auth-oauth-device@^7.0.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.1.tgz#7b4f8f97cbcadbe9894d48cde4406dbdef39875a" + integrity sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg== + dependencies: + "@octokit/oauth-methods" "^5.0.0" + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-user@^5.0.1", "@octokit/auth-oauth-user@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.1.tgz#4f1570c6ee15bb9ddc3dcca83308dcaa159e3848" + integrity sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw== + dependencies: + "@octokit/auth-oauth-device" "^7.0.1" + "@octokit/oauth-methods" "^5.0.0" + "@octokit/request" "^9.0.1" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + "@octokit/auth-token@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== +"@octokit/auth-token@^5.0.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-5.1.1.tgz#3bbfe905111332a17f72d80bd0b51a3e2fa2cf07" + integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== + +"@octokit/core@6.1.2", "@octokit/core@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.2.tgz#20442d0a97c411612da206411e356014d1d1bd17" + integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== + dependencies: + "@octokit/auth-token" "^5.0.0" + "@octokit/graphql" "^8.0.0" + "@octokit/request" "^9.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.0.0" + before-after-hook "^3.0.2" + universal-user-agent "^7.0.0" + "@octokit/core@^5.0.1", "@octokit/core@^5.0.2": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" @@ -1667,6 +1736,14 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/endpoint@^10.0.0": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.1.tgz#1a9694e7aef6aa9d854dc78dd062945945869bcc" + integrity sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q== + dependencies: + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.2" + "@octokit/endpoint@^9.0.1": version "9.0.5" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.5.tgz#e6c0ee684e307614c02fc6ac12274c50da465c44" @@ -1684,6 +1761,30 @@ "@octokit/types" "^13.0.0" universal-user-agent "^6.0.0" +"@octokit/graphql@^8.0.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.1.1.tgz#3cacab5f2e55d91c733e3bf481d3a3f8a5f639c4" + integrity sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg== + dependencies: + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/oauth-authorization-url@^7.0.0": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz#0e17c2225eb66b58ec902d02b6f1315ffe9ff04b" + integrity sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA== + +"@octokit/oauth-methods@^5.0.0": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-5.1.2.tgz#fd31d2a69f4c91d1abc1ed1814dda5252c697e02" + integrity sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g== + dependencies: + "@octokit/oauth-authorization-url" "^7.0.0" + "@octokit/request" "^9.1.0" + "@octokit/request-error" "^6.1.0" + "@octokit/types" "^13.0.0" + "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" @@ -1699,6 +1800,11 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.2.1.tgz#08b974f1e83a75c4d3ce23f798c7667b433bf4cd" integrity sha512-msAU1oTSm0ZmvAE0xDemuF4tVs5i0xNnNGtNmr4EuATi+1Rn8cZDetj6NXioSf5LwnxEc209COa/WOSbjuhLUA== +"@octokit/openapi-webhooks-types@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz#a7a4da00c0f27f7f5708eb3fcebefa08f8d51125" + integrity sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg== + "@octokit/plugin-paginate-rest@11.3.1": version "11.3.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz#fe92d04b49f134165d6fbb716e765c2f313ad364" @@ -1706,6 +1812,20 @@ dependencies: "@octokit/types" "^13.5.0" +"@octokit/plugin-paginate-rest@11.3.3": + version "11.3.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz#efc97ba66aae6797e2807a082f99b9cfc0e05aba" + integrity sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA== + dependencies: + "@octokit/types" "^13.5.0" + +"@octokit/plugin-paginate-rest@^11.0.0": + version "11.3.5" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz#a1929b3ba3dc7b63bc73bb6d3c7a3faf2a9c7649" + integrity sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ== + dependencies: + "@octokit/types" "^13.6.0" + "@octokit/plugin-paginate-rest@^9.0.0": version "9.2.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz#2e2a2f0f52c9a4b1da1a3aa17dabe3c459b9e401" @@ -1718,6 +1838,11 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz#98a3ca96e0b107380664708111864cb96551f958" integrity sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA== +"@octokit/plugin-request-log@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz#ccb75d9705de769b2aa82bcd105cc96eb0c00f69" + integrity sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw== + "@octokit/plugin-rest-endpoint-methods@13.2.2": version "13.2.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz#af8e5dd2cddfea576f92ffaf9cb84659f302a638" @@ -1725,6 +1850,13 @@ dependencies: "@octokit/types" "^13.5.0" +"@octokit/plugin-rest-endpoint-methods@13.2.4": + version "13.2.4" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.4.tgz#543add032d3fe3f5d2839bfd619cf66d85469f01" + integrity sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw== + dependencies: + "@octokit/types" "^13.5.0" + "@octokit/plugin-rest-endpoint-methods@^10.0.0": version "10.4.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz#41ba478a558b9f554793075b2e20cd2ef973be17" @@ -1732,6 +1864,30 @@ dependencies: "@octokit/types" "^12.6.0" +"@octokit/plugin-rest-endpoint-methods@^13.0.0": + version "13.2.6" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.6.tgz#b9d343dbe88a6cb70cc7fa16faa98f0a29ffe654" + integrity sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw== + dependencies: + "@octokit/types" "^13.6.1" + +"@octokit/plugin-retry@7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz#a84483e4afdd068dd71da81abe206a9e442c1288" + integrity sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw== + dependencies: + "@octokit/request-error" "^6.0.0" + "@octokit/types" "^13.0.0" + bottleneck "^2.15.3" + +"@octokit/plugin-throttling@9.3.1": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-9.3.1.tgz#5648165e1e70e861625f3a16af6c55cafe861061" + integrity sha512-Qd91H4liUBhwLB2h6jZ99bsxoQdhgPk6TdwnClPyTBSDAdviGPceViEgUwj+pcQDmB/rfAXAXK7MTochpHM3yQ== + dependencies: + "@octokit/types" "^13.0.0" + bottleneck "^2.15.3" + "@octokit/request-error@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" @@ -1741,6 +1897,13 @@ deprecation "^2.0.0" once "^1.4.0" +"@octokit/request-error@^6.0.0", "@octokit/request-error@^6.1.0", "@octokit/request-error@^6.1.1": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.5.tgz#907099e341c4e6179db623a0328d678024f54653" + integrity sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ== + dependencies: + "@octokit/types" "^13.0.0" + "@octokit/request-error@^6.0.1": version "6.1.1" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.1.tgz#bed1b5f52ce7fefb1077a92bf42124ff36f73f2c" @@ -1758,6 +1921,16 @@ "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" +"@octokit/request@^9.0.0", "@octokit/request@^9.0.1", "@octokit/request@^9.1.0", "@octokit/request@^9.1.1": + version "9.1.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.1.3.tgz#42b693bc06238f43af3c037ebfd35621c6457838" + integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== + dependencies: + "@octokit/endpoint" "^10.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.1.0" + universal-user-agent "^7.0.2" + "@octokit/rest@^20.0.2": version "20.1.1" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-20.1.1.tgz#ec775864f53fb42037a954b9a40d4f5275b3dc95" @@ -1768,6 +1941,16 @@ "@octokit/plugin-request-log" "^4.0.0" "@octokit/plugin-rest-endpoint-methods" "13.2.2" +"@octokit/rest@^21.0.2": + version "21.0.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-21.0.2.tgz#9b767dbc1098daea8310fd8b76bf7a97215d5972" + integrity sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ== + dependencies: + "@octokit/core" "^6.1.2" + "@octokit/plugin-paginate-rest" "^11.0.0" + "@octokit/plugin-request-log" "^5.3.1" + "@octokit/plugin-rest-endpoint-methods" "^13.0.0" + "@octokit/types@^12.6.0": version "12.6.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.6.0.tgz#8100fb9eeedfe083aae66473bd97b15b62aedcb2" @@ -1782,11 +1965,32 @@ dependencies: "@octokit/openapi-types" "^22.2.0" +"@octokit/types@^13.4.1", "@octokit/types@^13.6.0", "@octokit/types@^13.6.1": + version "13.6.1" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.6.1.tgz#432fc6c0aaae54318e5b2d3e15c22ac97fc9b15f" + integrity sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g== + dependencies: + "@octokit/openapi-types" "^22.2.0" + "@octokit/webhooks-methods@^5.0.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-5.1.0.tgz#13b6c08f89902c1ab0ddf31c6eeeec9c2772cfe6" integrity sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ== +"@octokit/webhooks-types@7.5.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-types/-/webhooks-types-7.5.1.tgz#e05399ab6bbbef8b78eb6bfc1a2cb138ea861104" + integrity sha512-1dozxWEP8lKGbtEu7HkRbK1F/nIPuJXNfT0gd96y6d3LcHZTtRtlf8xz3nicSJfesADxJyDh+mWBOsdLkqgzYw== + +"@octokit/webhooks@13.3.0": + version "13.3.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.3.0.tgz#fd5d54d47c789c75d60a00eb04e982152d7c654a" + integrity sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg== + dependencies: + "@octokit/openapi-webhooks-types" "8.3.0" + "@octokit/request-error" "^6.0.1" + "@octokit/webhooks-methods" "^5.0.0" + "@octokit/webhooks@^13.1.0": version "13.2.7" resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.2.7.tgz#03f89b278cd63f271eba3062f0b75ddd18a82252" @@ -1927,15 +2131,20 @@ "@pnpm/resolve-workspace-range" "5.0.1" ramda "npm:@pnpm/ramda@0.28.1" +"@sinclair/typebox@0.32.35": + version "0.32.35" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.35.tgz#41c04473509478df9895800018a3d3ae7d40fb3c" + integrity sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sinclair/typebox@^0.32.15": - version "0.32.29" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.29.tgz#35a31aac1078f14b722bd08086cea44fa73b206a" - integrity sha512-GWKskKPGQV0vVYizqCu0E1YLwGthvlkDqpRxB3iBuqxJ8dN/9n1cnDRSQHF59GMoxDJwzSgmxpU617SidtUnMw== +"@sinclair/typebox@^0.33.17": + version "0.33.17" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.33.17.tgz#603475bb1fb343deb82a4ce85e6adf177a65739b" + integrity sha512-75232GRx3wp3P7NP+yc4nRK3XUAnaQShxTAzapgmQrgs0QvSq0/mOJGoZXRpH15cFCKyys+4laCPbBselqJ5Ag== "@sinonjs/commons@^3.0.0": version "3.0.1" @@ -2307,6 +2516,38 @@ "@typescript-eslint/types" "7.0.1" eslint-visitor-keys "^3.4.1" +"@ubiquity-os/ubiquity-os-kernel@^2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@ubiquity-os/ubiquity-os-kernel/-/ubiquity-os-kernel-2.5.1.tgz#13cc77146837deeb7a6e6346511a686be78a832b" + integrity sha512-G+gL/NmZTP7QiijB1CcHXBj78iKW7RYdRC80ETWxzojIR3fZYPxTSb3rWEJOim9iAfQ7qGawJQJGL1yrPuMRBQ== + dependencies: + "@actions/core" "1.10.1" + "@actions/github" "6.0.0" + "@cfworker/json-schema" "2.0.1" + "@octokit/auth-app" "7.1.0" + "@octokit/core" "6.1.2" + "@octokit/plugin-paginate-rest" "11.3.3" + "@octokit/plugin-rest-endpoint-methods" "13.2.4" + "@octokit/plugin-retry" "7.1.1" + "@octokit/plugin-throttling" "9.3.1" + "@octokit/rest" "^21.0.2" + "@octokit/types" "^13.5.0" + "@octokit/webhooks" "13.3.0" + "@octokit/webhooks-types" "7.5.1" + "@sinclair/typebox" "0.32.35" + "@ubiquity-os/ubiquity-os-logger" "^1.3.2" + dotenv "16.4.5" + hono "4.4.13" + smee-client "2.0.1" + ts-node "^10.9.2" + typebox-validators "0.3.5" + yaml "2.4.5" + +"@ubiquity-os/ubiquity-os-logger@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@ubiquity-os/ubiquity-os-logger/-/ubiquity-os-logger-1.3.2.tgz#4423bc0baeac5c2f73123d15fd961310521163cd" + integrity sha512-oTIzR8z4jAQmaeJp98t1bZUKE3Ws9pas0sbxt58fC37MwXclPMWrLO+a0JlhPkdJYsvpv/q/79wC2MKVhOIVXQ== + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -2609,6 +2850,11 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== +before-after-hook@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" + integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== + bin-links@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.4.tgz#c3565832b8e287c85f109a02a17027d152a58a63" @@ -2637,6 +2883,11 @@ bole@^5.0.0: fast-safe-stringify "^2.0.7" individual "^3.0.0" +bottleneck@^2.15.3: + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -3387,7 +3638,7 @@ dotenv-expand@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== -dotenv@^16.3.0, dotenv@^16.4.5: +dotenv@16.4.5, dotenv@^16.3.0, dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== @@ -3719,6 +3970,11 @@ eventemitter3@^5.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== +eventsource@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" + integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== + execa@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" @@ -4237,6 +4493,11 @@ headers-polyfill@^4.0.2: resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.2.tgz#9115a76eee3ce8fbf95b6e3c6bf82d936785b44a" integrity sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw== +hono@4.4.13: + version "4.4.13" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.4.13.tgz#954e8f6e4bab14f3f9d7bac4eef4c56d23e7f900" + integrity sha512-c6qqenclmQ6wpXzqiElMa2jt423PVCmgBreDfC5s2lPPpGk7d0lOymd8QTzFZyYC5mSSs6imiTMPip+gLwuW/g== + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -5342,6 +5603,11 @@ log-update@^6.0.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" +lru-cache@^10.0.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^10.0.1, lru-cache@^10.0.2, "lru-cache@^9.1.1 || ^10.0.0": version "10.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" @@ -6580,6 +6846,15 @@ slice-ansi@^7.0.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" +smee-client@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/smee-client/-/smee-client-2.0.1.tgz#348a644c3499cc7687fcb42fbbaeeeb3211a365d" + integrity sha512-s2+eG9vNMWQQvu8Jz+SfAiihpYsmaMtcyPnHtBuZEhaAAQOQV63xSSL9StWv2p08xKgvSC8pEZ28rXoy41FhLg== + dependencies: + commander "^12.0.0" + eventsource "^2.0.2" + validator "^13.11.0" + smol-toml@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.1.4.tgz#08c23b105f56f17e57b0a77c7edcb10b75a62c5c" @@ -6987,7 +7262,7 @@ ts-jest@29.1.2: semver "^7.5.3" yargs-parser "^21.0.1" -ts-node@10.9.2: +ts-node@10.9.2, ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== @@ -7192,11 +7467,21 @@ unique-string@^3.0.0: dependencies: crypto-random-string "^4.0.0" +universal-github-app-jwt@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz#dc6c8929e76f1996a766ba2a08fb420f73365d77" + integrity sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ== + universal-user-agent@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== +universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" + integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -7263,6 +7548,11 @@ validate-npm-package-name@^5.0.0: dependencies: builtins "^5.0.0" +validator@^13.11.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== + version-selector-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/version-selector-type/-/version-selector-type-3.0.0.tgz#47c365fb4d9ca4a54e6dabcad6fb7a46265f7955" @@ -7522,6 +7812,11 @@ yaml@2.3.4, yaml@^2.3.4: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== +yaml@2.4.5: + version "2.4.5" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" + integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== + yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" From 20dcee96aa187f0dd8c7dee95a95a7e1fe98fa1e Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:55:03 +0900 Subject: [PATCH 02/22] fix: support ESM and update configurations Added ESM support in Jest and package.json, updated moduleResolution in tsconfig. --- jest.config.ts | 12 ++++++++++++ package.json | 2 ++ src/types/env.ts | 4 ---- src/types/plugin-input.ts | 13 ------------- tests/main.test.ts | 4 ++-- tsconfig.json | 4 ++-- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index a6555b0..5bb35e7 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -9,4 +9,16 @@ module.exports = { coverageReporters: ["json", "lcov", "text", "clover", "json-summary"], reporters: ["default", "jest-junit", "jest-md-dashboard"], coverageDirectory: "coverage", + extensionsToTreatAsEsm: [".ts"], + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1", + }, + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true, + }, + ], + }, } as JestConfigWithTsJest; diff --git a/package.json b/package.json index a25a4d4..45c1be9 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "engines": { "node": ">=20.10.0" }, + "type": "module", "scripts": { "worker": "wrangler dev --env dev --port 4000", "start": "tsx src/index.ts", @@ -38,6 +39,7 @@ "@sinclair/typebox": "^0.33.17", "@supabase/supabase-js": "2.43.1", "@ubiquity-os/ubiquity-os-kernel": "^2.5.1", + "@ubiquity-os/ubiquity-os-logger": "^1.3.2", "commander": "12.0.0", "decimal.js": "^10.4.3", "dotenv": "^16.4.5" diff --git a/src/types/env.ts b/src/types/env.ts index 6b826ef..d54dd7f 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -1,6 +1,4 @@ import { StaticDecode, Type as T } from "@sinclair/typebox"; -import "dotenv/config"; -import { StandardValidator } from "typebox-validators"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), @@ -8,6 +6,4 @@ export const envSchema = T.Object({ UBIQUIBOT_PUBLIC_KEY: T.String(), }); -export const envConfigValidator = new StandardValidator(envSchema); - export type Env = StaticDecode; diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 9833e50..943e4de 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -1,20 +1,9 @@ -import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks"; import { StaticDecode, Type as T } from "@sinclair/typebox"; import { Context } from "@ubiquity-os/ubiquity-os-kernel"; -import { StandardValidator } from "typebox-validators"; import { createAdapters } from "../adapters"; import { SupportedEvents } from "./context"; import { Env } from "./env"; -export interface PluginInputs { - stateId: string; - eventName: T; - eventPayload: WebhookEvent["payload"]; - settings: AssistivePricingSettings; - authToken: string; - ref: string; -} - export const pluginSettingsSchema = T.Object( { labels: T.Object( @@ -36,8 +25,6 @@ export const pluginSettingsSchema = T.Object( { default: {} } ); -export const assistivePricingSchemaValidator = new StandardValidator(pluginSettingsSchema); - export type AssistivePricingSettings = StaticDecode; export type ContextPlugin = Context & { adapters: ReturnType }; diff --git a/tests/main.test.ts b/tests/main.test.ts index 5bb21f0..b4dafa8 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -1,4 +1,4 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { drop } from "@mswjs/data"; import * as crypto from "crypto"; import commandParser, { CommandArguments } from "../src/handlers/command-parser"; @@ -23,7 +23,7 @@ const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { }, }); -const url = "http://localhost:4000"; +const url = "/"; beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); diff --git a/tsconfig.json b/tsconfig.json index f9ab3da..8c39d70 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,7 @@ /* Modules */ "module": "commonjs" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -104,7 +104,7 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */, "resolveJsonModule": true } } From b26d8331964c5c215c4594e9388a13c595558c6c Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:59:33 +0900 Subject: [PATCH 03/22] chore: remove validator and update test script Deleted `validator.ts`, removed unused dependencies, and updated the test script in `package.json`. --- package.json | 4 +--- src/handlers/validator.ts | 35 ----------------------------------- yarn.lock | 4 ++-- 3 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 src/handlers/validator.ts diff --git a/package.json b/package.json index 45c1be9..4af4a33 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "knip": "knip --config .github/knip.ts", "knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts", "prepare": "husky install", - "test": "jest --setupFiles dotenv/config --coverage", + "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --setupFiles dotenv/config --coverage", "supabase:generate:local": "supabase gen types typescript --local > src/adapters/supabase/types/database.ts", "supabase:generate:remote": "dotenv -- cross-env-shell supabase gen types typescript --project-id $SUPABASE_PROJECT_ID --schema public > src/adapters/supabase/types/database.ts" }, @@ -31,8 +31,6 @@ "open-source" ], "dependencies": { - "@actions/core": "^1.10.1", - "@actions/github": "^6.0.0", "@commander-js/extra-typings": "12.0.1", "@octokit/rest": "^20.0.2", "@octokit/webhooks": "^13.1.0", diff --git a/src/handlers/validator.ts b/src/handlers/validator.ts deleted file mode 100644 index f2f96c3..0000000 --- a/src/handlers/validator.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { TransformDecodeCheckError, TransformDecodeError, Value, ValueError } from "@sinclair/typebox/value"; -import { Env, envConfigValidator, envSchema } from "../types/env"; -import { assistivePricingSchemaValidator, AssistivePricingSettings, pluginSettingsSchema } from "../types/plugin-input"; - -export function validateAndDecodeSchemas(env: Env, rawSettings: object) { - const errors: ValueError[] = []; - const settings = Value.Default(pluginSettingsSchema, rawSettings) as AssistivePricingSettings; - - if (!assistivePricingSchemaValidator.test(settings)) { - for (const error of assistivePricingSchemaValidator.errors(settings)) { - errors.push(error); - } - } - - if (!envConfigValidator.test(env)) { - for (const error of envConfigValidator.errors(env)) { - errors.push(error); - } - } - - if (errors.length) { - throw { errors }; - } - - try { - const decodedEnv = Value.Decode(envSchema, 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/yarn.lock b/yarn.lock index 1882185..f411181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@actions/core@1.10.1", "@actions/core@^1.10.1": +"@actions/core@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a" integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g== @@ -15,7 +15,7 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" -"@actions/github@6.0.0", "@actions/github@^6.0.0": +"@actions/github@6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.0.tgz#65883433f9d81521b782a64cc1fd45eef2191ea7" integrity sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g== From f1234e436092918149191a0521fa44507bca3b65 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:09:06 +0900 Subject: [PATCH 04/22] test: update URL and adjust expectations in test case Update the URL in the fetch call and modify the expected response status and `ok` flag. --- tests/main.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/main.test.ts b/tests/main.test.ts index b4dafa8..8366d33 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -163,7 +163,7 @@ describe("User tests", () => { const result = await workerFetch.fetch( { method: "GET", - url, + url: `${url}/manifest.json`, } as unknown as Request, { SUPABASE_URL: "url", @@ -171,8 +171,8 @@ describe("User tests", () => { UBIQUIBOT_PUBLIC_KEY: "key", } ); - expect(result.ok).toEqual(false); - expect(result.status).toEqual(405); + expect(result.ok).toEqual(true); + expect(result.status).toEqual(200); }); it("Should reject an invalid environment", async () => { From 5a4670bc4e51893ee1b6be9f4c0d4493450b4a6b Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:21:19 +0900 Subject: [PATCH 05/22] test: correct stateId and user login in mock JSON file Updated `stateId` in `issue-comment-post.json --- .../requests/issue-comment-post.json | 3 ++- tests/main.test.ts | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/__mocks__/requests/issue-comment-post.json b/tests/__mocks__/requests/issue-comment-post.json index 33c6da3..d57bbc1 100644 --- a/tests/__mocks__/requests/issue-comment-post.json +++ b/tests/__mocks__/requests/issue-comment-post.json @@ -1,5 +1,5 @@ { - "stateId": "", + "stateId": "1234", "eventName": "issue_comment.created", "eventPayload": { "action": "created", @@ -15,6 +15,7 @@ "number": 5, "title": "New issue", "user": { + "login": "gentlementlegen", "login": "gentlementlegen", "id": 9807008, "node_id": "MDQ6VXNlcjk4MDcwMDg=", diff --git a/tests/main.test.ts b/tests/main.test.ts index 8366d33..e7370d0 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -129,10 +129,7 @@ describe("User tests", () => { }); it("Should handle the comment", async () => { - const data = { - ...issueCommented, - authToken: process.env.GITHUB_TOKEN, - }; + const data = issueCommented; const sign = crypto.createSign("SHA256"); sign.update(JSON.stringify(data)); sign.end(); @@ -163,7 +160,7 @@ describe("User tests", () => { const result = await workerFetch.fetch( { method: "GET", - url: `${url}/manifest.json`, + url, } as unknown as Request, { SUPABASE_URL: "url", @@ -171,11 +168,16 @@ describe("User tests", () => { UBIQUIBOT_PUBLIC_KEY: "key", } ); - expect(result.ok).toEqual(true); - expect(result.status).toEqual(200); + expect(result.ok).toEqual(false); + expect(result.status).toEqual(404); }); it("Should reject an invalid environment", async () => { + const data = issueCommented; + const sign = crypto.createSign("SHA256"); + sign.update(JSON.stringify(data)); + sign.end(); + const signature = sign.sign(privateKey, "base64"); const result = await workerFetch.fetch( { method: "POST", @@ -183,9 +185,10 @@ describe("User tests", () => { get: () => "application/json", }, url, - json() { - return { settings: {} }; - }, + json: () => ({ + ...data, + signature, + }), } as unknown as Request, { SUPABASE_URL: "url", @@ -193,7 +196,7 @@ describe("User tests", () => { } as unknown as Env ); expect(result.ok).toEqual(false); - expect(result.status).toEqual(500); + expect(result.status).toEqual(400); expect(await result.json()).toEqual({ errors: [ { From 714f6ae21cd66e974d766515f8e7385e1384ff6a Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:45:41 +0900 Subject: [PATCH 06/22] chore: integrate fetch handler with createPlugin method Enhanced plugin setup by adding fetch handler to handle requests --- .cspell.json | 2 +- src/types/env.ts | 3 ++ src/worker.ts | 34 ++++++++++++------- .../requests/issue-comment-post.json | 1 - 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.cspell.json b/.cspell.json index 7ba6fa9..ac3df8e 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,7 +4,7 @@ "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "**/*.toml", "**/*.http", "src/adapters/supabase/types/database.ts"], "useGitignore": true, "language": "en", - "words": ["dataurl", "devpool", "outdir", "servedir", "supabase", "typebox", "typeguards", "mswjs", "ubiquity-os"], + "words": ["dataurl", "devpool", "outdir", "servedir", "supabase", "typebox", "typeguards", "mswjs", "ubiquity-os", "hono"], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/src/types/env.ts b/src/types/env.ts index d54dd7f..e5383cc 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -1,9 +1,12 @@ import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { LOG_LEVEL } from "@ubiquity-os/ubiquity-os-logger"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), UBIQUIBOT_PUBLIC_KEY: T.String(), + LOG_LEVEL: T.Optional(T.Enum(LOG_LEVEL)), + KERNEL_PUBLIC_KEY: T.Optional(T.String()), }); export type Env = StaticDecode; diff --git a/src/worker.ts b/src/worker.ts index 3852a86..3946d65 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,5 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import type { ExecutionContext } from "hono/dist/types/context"; import { createAdapters } from "./adapters"; import { run } from "./run"; import { SupportedEvents } from "./types/context"; @@ -7,17 +8,24 @@ import { Env, envSchema } from "./types/env"; import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; import manifest from "../manifest.json"; -export default createPlugin( - (context) => { - return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); +export default { + async fetch(request: Request, env: Env, executionCtx?: ExecutionContext) { + return createPlugin( + (context) => { + return run({ + ...context, + adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context), + }); + }, + //@ts-expect-error types are ok + manifest, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: env.LOG_LEVEL, + kernelPublicKey: env.KERNEL_PUBLIC_KEY, + } + ).fetch(request, env, executionCtx); }, - //@ts-expect-error types are ok - manifest, - { - envSchema: envSchema, - postCommentOnError: true, - settingsSchema: pluginSettingsSchema, - logLevel: process.env.LOG_LEVEL, - kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, - } -); +}; diff --git a/tests/__mocks__/requests/issue-comment-post.json b/tests/__mocks__/requests/issue-comment-post.json index d57bbc1..1cc459e 100644 --- a/tests/__mocks__/requests/issue-comment-post.json +++ b/tests/__mocks__/requests/issue-comment-post.json @@ -15,7 +15,6 @@ "number": 5, "title": "New issue", "user": { - "login": "gentlementlegen", "login": "gentlementlegen", "id": 9807008, "node_id": "MDQ6VXNlcjk4MDcwMDg=", From 114ed8aa6c9bb96aed5a0f9bd330f6b6c55a22fc Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:47:54 +0900 Subject: [PATCH 07/22] chore: update import for ExecutionContext Simplify type import for ExecutionContext from 'hono' package. --- src/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/worker.ts b/src/worker.ts index 3946d65..5720630 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,6 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; -import type { ExecutionContext } from "hono/dist/types/context"; +import type { ExecutionContext } from "hono"; import { createAdapters } from "./adapters"; import { run } from "./run"; import { SupportedEvents } from "./types/context"; From f8c1ee736237fd471469935bb04af2a298b049c2 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:49:50 +0900 Subject: [PATCH 08/22] chore(package): add Hono framework dependency Added Hono framework version 4.6.7 to project dependencies in package.json and updated yarn.lock. --- package.json | 3 ++- yarn.lock | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4af4a33..27cfcd9 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "@ubiquity-os/ubiquity-os-logger": "^1.3.2", "commander": "12.0.0", "decimal.js": "^10.4.3", - "dotenv": "^16.4.5" + "dotenv": "^16.4.5", + "hono": "^4.6.7" }, "devDependencies": { "@commitlint/cli": "^18.6.1", diff --git a/yarn.lock b/yarn.lock index f411181..01de3a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4498,6 +4498,11 @@ hono@4.4.13: resolved "https://registry.yarnpkg.com/hono/-/hono-4.4.13.tgz#954e8f6e4bab14f3f9d7bac4eef4c56d23e7f900" integrity sha512-c6qqenclmQ6wpXzqiElMa2jt423PVCmgBreDfC5s2lPPpGk7d0lOymd8QTzFZyYC5mSSs6imiTMPip+gLwuW/g== +hono@^4.6.7: + version "4.6.7" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.6.7.tgz#5389be797be4e049991d29ad7aea499e70d28085" + integrity sha512-wX4ZbOnzfNO61hUjuQbJ7OPGs1fWXXVVJ8VTPDb2Ls/x9HjCbVTm80Je6VTHMz5n5RGDtBgV9d9ZFZxBqx56ng== + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" From 84b8af8f6476a24c2f1d2f16a3987d8b34b91a46 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 00:51:57 +0900 Subject: [PATCH 09/22] chore: update dependencies and configuration Updated wrangler settings, updated to latest package versions. --- package.json | 2 +- wrangler.toml | 7 ++- yarn.lock | 122 +++++++++++++++++++++++++++----------------------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 27cfcd9..40552d9 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "ts-node": "10.9.2", "tsx": "^4.7.1", "typescript": "5.6.2", - "wrangler": "3.79.0" + "wrangler": "^3.83.0" }, "lint-staged": { "*.ts": [ diff --git a/wrangler.toml b/wrangler.toml index fc0f65a..469c0ed 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,9 @@ name = "ubiquity-os-daemon-pricing" main = "src/worker.ts" -compatibility_date = "2024-01-01" -node_compat = true +compatibility_date = "2024-09-23" +compatibility_flags = [ "nodejs_compat" ] [env.dev] [env.prod] + +[observability] +enabled = true \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 01de3a1..2c262d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -361,35 +361,35 @@ dependencies: mime "^3.0.0" -"@cloudflare/workerd-darwin-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240925.0.tgz#f78fe394f73540594609d8e05a2da7feb46c76c0" - integrity sha512-KdLnSXuzB65CbqZPm+qYzk+zkQ1tUNPaaRGYVd/jPYAxwwtfTUQdQ+ahDPwVVs2tmQELKy7ZjQjf2apqSWUfjw== - -"@cloudflare/workerd-darwin-arm64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240925.0.tgz#f03b17177744ad898bb12610d15cc0a9744abfe6" - integrity sha512-MiQ6uUmCXjsXgWNV+Ock2tp2/tYqNJGzjuaH6jFioeRF+//mz7Tv7J7EczOL4zq+TH8QFOh0/PUsLyazIWVGng== - -"@cloudflare/workerd-linux-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240925.0.tgz#fe0366b804b957acf5012d889e94163bab806a57" - integrity sha512-Rjix8jsJMfsInmq3Hm3fmiRQ+rwzuWRPV1pg/OWhMSfNP7Qp2RCU+RGkhgeR9Z5eNAje0Sn2BMrFq4RvF9/yRA== - -"@cloudflare/workerd-linux-arm64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240925.0.tgz#fcf82de06def420972c661a6021c87683cd8fbdc" - integrity sha512-VYIPeMHQRtbwQoIjUwS/zULlywPxyDvo46XkTpIW5MScEChfqHvAYviQ7TzYGx6Q+gmZmN+DUB2KOMx+MEpCxA== - -"@cloudflare/workerd-windows-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240925.0.tgz#0a5c82b95b03a94591cc8a1830f28d2e41ff7685" - integrity sha512-C8peGvaU5R51bIySi1VbyfRgwNSSRknqoFSnSbSBI3uTN3THTB3UnmRKy7GXJDmyjgXuT9Pcs1IgaWNubLtNtw== - -"@cloudflare/workers-shared@0.5.4": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.5.4.tgz#bbf8f03b79a6bc0169ad66a6015ebe579d36753a" - integrity sha512-PNL/0TjKRdUHa1kwgVdqUNJVZ9ez4kacsi8omz+gv859EvJmsVuGiMAClY2YfJnC9LVKhKCcjqmFgKNXG9/IXA== +"@cloudflare/workerd-darwin-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241022.0.tgz#1d22149152ad32672971e3be48ab1491ff236eb3" + integrity sha512-1NNYun37myMTgCUiPQEJ0cMal4mKZVTpkD0b2tx9hV70xji+frVJcSK8YVLeUm1P+Rw1d/ct8DMgQuCpsz3Fsw== + +"@cloudflare/workerd-darwin-arm64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241022.0.tgz#6ec4e4fd1427ac09d9cfea38db849799755029e5" + integrity sha512-FOO/0P0U82EsTLTdweNVgw+4VOk5nghExLPLSppdOziq6IR5HVgP44Kmq5LdsUeHUhwUmfOh9hzaTpkNzUqKvw== + +"@cloudflare/workerd-linux-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241022.0.tgz#0297222e46ce8b2c55b591ae87ee2bbb85830e20" + integrity sha512-RsNc19BQJG9yd+ngnjuDeG9ywZG+7t1L4JeglgceyY5ViMNMKVO7Zpbsu69kXslU9h6xyQG+lrmclg3cBpnhYA== + +"@cloudflare/workerd-linux-arm64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241022.0.tgz#7637092b14129c94ddb87990221d38623e4fd498" + integrity sha512-x5mUXpKxfsosxcFmcq5DaqLs37PejHYVRsNz1cWI59ma7aC4y4Qn6Tf3i0r9MwQTF/MccP4SjVslMU6m4W7IaA== + +"@cloudflare/workerd-windows-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241022.0.tgz#64f05a2bc475e1450154942c060555184e6350de" + integrity sha512-eBCClx4szCOgKqOlxxbdNszMqQf3MRG1B9BRIqEM/diDfdR9IrZ8l3FaEm+l9gXgPmS6m1NBn40aWuGBl8UTSw== + +"@cloudflare/workers-shared@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.7.0.tgz#ecb6a3a1f483989c1ca10d5ed0592d01c7eff0c0" + integrity sha512-LLQRTqx7lKC7o2eCYMpyc5FXV8d0pUX6r3A+agzhqS9aoR5A6zCPefwQGcvbKx83ozX22ATZcemwxQXn12UofQ== dependencies: mime "^3.0.0" zod "^3.22.3" @@ -3488,6 +3488,11 @@ date-fns@^2.21.1: dependencies: "@babel/runtime" "^7.21.0" +date-fns@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" + integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== + debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -4928,6 +4933,11 @@ iterable-lookahead@^1.0.0: resolved "https://registry.yarnpkg.com/iterable-lookahead/-/iterable-lookahead-1.0.0.tgz#896dfcb78680bdb50036e97edb034c8b68a9737f" integrity sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ== +itty-time@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/itty-time/-/itty-time-1.0.6.tgz#a6eeda619f19d2f4c480ceddd013b93acb05714d" + integrity sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw== + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -5787,10 +5797,10 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -miniflare@3.20240925.0: - version "3.20240925.0" - resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240925.0.tgz#a291998dedf90bfb4bcfdad033ba030851ff9171" - integrity sha512-2LmQbKHf0n6ertUKhT+Iltixi53giqDH7P71+wCir3OnGyXIODqYwOECx1mSDNhYThpxM2dav8UdPn6SQiMoXw== +miniflare@3.20241022.0: + version "3.20241022.0" + resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20241022.0.tgz#31b8a2bc53b411ac814b55db9c31aebfe475f344" + integrity sha512-x9Fbq1Hmz1f0osIT9Qmj78iX4UpCP2EqlZnA/tzj/3+I49vc3Kq0fNqSSKplcdf6HlCHdL3fOBicmreQF4BUUQ== dependencies: "@cspotcode/source-map-support" "0.8.1" acorn "^8.8.0" @@ -5800,7 +5810,7 @@ miniflare@3.20240925.0: glob-to-regexp "^0.4.1" stoppable "^1.1.0" undici "^5.28.4" - workerd "1.20240925.0" + workerd "1.20241022.0" ws "^8.17.1" youch "^3.2.2" zod "^3.22.3" @@ -7441,10 +7451,10 @@ undici@^5.25.4, undici@^5.28.4: dependencies: "@fastify/busboy" "^2.0.0" -"unenv@npm:unenv-nightly@2.0.0-20240919-125358-9a64854": - version "2.0.0-20240919-125358-9a64854" - resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20240919-125358-9a64854.tgz#13f6812c7b12b9521ea05c6d49259d136e093acd" - integrity sha512-XjsgUTrTHR7iw+k/SRTNjh6EQgwpC9voygnoCJo5kh4hKqsSDHUW84MhL9EsHTNfLctvVBHaSw8e2k3R2fKXsQ== +"unenv@npm:unenv-nightly@2.0.0-20241018-011344-e666fcf": + version "2.0.0-20241018-011344-e666fcf" + resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20241018-011344-e666fcf.tgz#75b6d1ab37e6b5edeec80fe8f403e3de8e9bc50e" + integrity sha512-D00bYn8rzkCBOlLx+k1iHQlc69jvtJRT7Eek4yIGQ6461a2tUBjngGZdRpqsoXAJCz/qBW0NgPting7Zvg+ysg== dependencies: defu "^6.1.4" ohash "^1.1.4" @@ -7655,38 +7665,40 @@ which@^4.0.0: dependencies: isexe "^3.1.1" -workerd@1.20240925.0: - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240925.0.tgz#0a2602eabfa7e1d01d89ff2b600ed359be9b515d" - integrity sha512-/Jj6+yLwfieZGEt3Kx4+5MoufuC3g/8iFaIh4MPBNGJOGYmdSKXvgCqz09m2+tVCYnysRfbq2zcbVxJRBfOCqQ== +workerd@1.20241022.0: + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20241022.0.tgz#45ab10642009b4573ae78df784e0a8c5b338914e" + integrity sha512-jyGXsgO9DRcJyx6Ovv7gUyDPc3UYC2i/E0p9GFUg6GUzpldw4Y93y9kOmdfsOnKZ3+lY53veSiUniiBPE6Q2NQ== optionalDependencies: - "@cloudflare/workerd-darwin-64" "1.20240925.0" - "@cloudflare/workerd-darwin-arm64" "1.20240925.0" - "@cloudflare/workerd-linux-64" "1.20240925.0" - "@cloudflare/workerd-linux-arm64" "1.20240925.0" - "@cloudflare/workerd-windows-64" "1.20240925.0" + "@cloudflare/workerd-darwin-64" "1.20241022.0" + "@cloudflare/workerd-darwin-arm64" "1.20241022.0" + "@cloudflare/workerd-linux-64" "1.20241022.0" + "@cloudflare/workerd-linux-arm64" "1.20241022.0" + "@cloudflare/workerd-windows-64" "1.20241022.0" -wrangler@3.79.0: - version "3.79.0" - resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.79.0.tgz#c23b08ba06bff752b650a567a7fcbe03e4036914" - integrity sha512-29wzQWc5qNKtD3bSyAEX11j/U5IIk8xy2/ZJ4wljJlS5ppff8qGqI+LtlLmqjqTSeQqFLb87xRkms0YFUgNLXg== +wrangler@^3.83.0: + version "3.83.0" + resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.83.0.tgz#bebe3d0067f3430cf6f0b2e8e4ab648c208e002b" + integrity sha512-qDzdUuTngKqmm2OJUZm7Gk4+Hv37F2nNNAHuhIgItEIhxBdOVDsgKmvpd+f41MFxyuGg3fbGWYANHI+0V2Z5yw== dependencies: "@cloudflare/kv-asset-handler" "0.3.4" - "@cloudflare/workers-shared" "0.5.4" + "@cloudflare/workers-shared" "0.7.0" "@esbuild-plugins/node-globals-polyfill" "^0.2.3" "@esbuild-plugins/node-modules-polyfill" "^0.2.2" blake3-wasm "^2.1.5" chokidar "^3.5.3" + date-fns "^4.1.0" esbuild "0.17.19" - miniflare "3.20240925.0" + itty-time "^1.0.6" + miniflare "3.20241022.0" nanoid "^3.3.3" path-to-regexp "^6.3.0" resolve "^1.22.8" resolve.exports "^2.0.2" selfsigned "^2.0.1" source-map "^0.6.1" - unenv "npm:unenv-nightly@2.0.0-20240919-125358-9a64854" - workerd "1.20240925.0" + unenv "npm:unenv-nightly@2.0.0-20241018-011344-e666fcf" + workerd "1.20241022.0" xxhash-wasm "^1.0.1" optionalDependencies: fsevents "~2.3.2" From d08b790066ecd6d324fb36345cfe730a146529aa Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 01:10:48 +0900 Subject: [PATCH 10/22] refactor: replace UBIQUIBOT_PUBLIC_KEY with KERNEL_PUBLIC_KEY Updated environment variable references and tests for consistency. --- .dev.vars.example | 2 +- .env.example | 2 +- .github/workflows/worker-deploy.yml | 4 ++-- src/types/env.ts | 1 - tests/__mocks__/handlers.ts | 1 + tests/main.test.ts | 33 ++++++----------------------- 6 files changed, 12 insertions(+), 31 deletions(-) diff --git a/.dev.vars.example b/.dev.vars.example index de67ce7..cda5c21 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -1,3 +1,3 @@ SUPABASE_URL= SUPABASE_KEY= -UBIQUIBOT_PUBLIC_KEY= +KERNEL_PUBLIC_KEY= diff --git a/.env.example b/.env.example index de67ce7..cda5c21 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,3 @@ SUPABASE_URL= SUPABASE_KEY= -UBIQUIBOT_PUBLIC_KEY= +KERNEL_PUBLIC_KEY= diff --git a/.github/workflows/worker-deploy.yml b/.github/workflows/worker-deploy.yml index ecc3241..3eced74 100644 --- a/.github/workflows/worker-deploy.yml +++ b/.github/workflows/worker-deploy.yml @@ -41,11 +41,11 @@ jobs: secrets: | SUPABASE_URL SUPABASE_KEY - UBIQUIBOT_PUBLIC_KEY + KERNEL_PUBLIC_KEY env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} - UBIQUIBOT_PUBLIC_KEY: ${{ secrets.UBIQUIBOT_PUBLIC_KEY }} + KERNEL_PUBLIC_KEY: ${{ secrets.KERNEL_PUBLIC_KEY }} - name: Write Deployment URL to Summary run: | diff --git a/src/types/env.ts b/src/types/env.ts index e5383cc..f0a09c7 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -4,7 +4,6 @@ import { LOG_LEVEL } from "@ubiquity-os/ubiquity-os-logger"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), - UBIQUIBOT_PUBLIC_KEY: T.String(), LOG_LEVEL: T.Optional(T.Enum(LOG_LEVEL)), KERNEL_PUBLIC_KEY: T.Optional(T.String()), }); diff --git a/tests/__mocks__/handlers.ts b/tests/__mocks__/handlers.ts index d5dd44d..e7b1125 100644 --- a/tests/__mocks__/handlers.ts +++ b/tests/__mocks__/handlers.ts @@ -9,4 +9,5 @@ export const handlers = [ http.post("https://api.github.com/repos/:org/:repo/issues/:id/comments", () => HttpResponse.json()), http.get("https://api.github.com/users/:user", () => HttpResponse.json()), http.get("https://api.github.com/orgs/:org/memberships/:user", () => HttpResponse.json()), + http.post("http://localhost:65432/rest/v1/access", () => HttpResponse.json()), ]; diff --git a/tests/main.test.ts b/tests/main.test.ts index e7370d0..764e753 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -148,9 +148,9 @@ describe("User tests", () => { url, } as unknown as Request, { - SUPABASE_URL: "url", + SUPABASE_URL: "http://localhost:65432", SUPABASE_KEY: "key", - UBIQUIBOT_PUBLIC_KEY: publicKey, + KERNEL_PUBLIC_KEY: publicKey, } ); expect(result.ok).toEqual(true); @@ -165,7 +165,7 @@ describe("User tests", () => { { SUPABASE_URL: "url", SUPABASE_KEY: "key", - UBIQUIBOT_PUBLIC_KEY: "key", + KERNEL_PUBLIC_KEY: "key", } ); expect(result.ok).toEqual(false); @@ -191,31 +191,12 @@ describe("User tests", () => { }), } as unknown as Request, { - SUPABASE_URL: "url", - SUPABASE_KEY: "key", + SUPABASE_URL: "http://localhost:65432", + KERNEL_PUBLIC_KEY: publicKey, } as unknown as Env ); expect(result.ok).toEqual(false); - expect(result.status).toEqual(400); - expect(await result.json()).toEqual({ - errors: [ - { - message: "Required property", - path: "/UBIQUIBOT_PUBLIC_KEY", - schema: { - type: "string", - }, - type: 45, - }, - { - message: "Expected string", - path: "/UBIQUIBOT_PUBLIC_KEY", - schema: { - type: "string", - }, - type: 54, - }, - ], - }); + expect(result.status).toEqual(500); + expect(await result.text()).toEqual("Internal Server Error"); }); }); From 8e60bca1115d4e42078b3590ed6841bebd2cde40 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:33:10 +0900 Subject: [PATCH 11/22] refactor: update Context type and enhance plugin structure Replaces `Context` with `ContextPlugin` in multiple files to utilize standardized context structure. --- package.json | 7 +- src/adapters/index.ts | 4 +- .../supabase/helpers/tables/access.ts | 2 +- src/adapters/supabase/helpers/tables/label.ts | 2 +- src/adapters/supabase/helpers/tables/super.ts | 2 +- src/adapters/supabase/helpers/tables/user.ts | 2 +- src/handlers/comment.ts | 6 +- src/handlers/handle-parent-issue.ts | 4 +- src/handlers/label-change.ts | 6 +- src/handlers/pricing-label.ts | 22 +++--- src/handlers/sync-labels-to-config.ts | 4 +- src/index.ts | 58 ++++++---------- src/run.ts | 28 ++------ src/shared/issue.ts | 16 ++--- src/shared/label.ts | 18 ++--- src/shared/permissions.ts | 4 +- src/shared/pricing.ts | 8 +-- src/types/plugin-input.ts | 7 +- src/types/typeguards.ts | 9 +-- src/worker.ts | 68 ++++++------------- tests/main.test.ts | 5 +- 21 files changed, 110 insertions(+), 172 deletions(-) diff --git a/package.json b/package.json index 43fad12..3004965 100644 --- a/package.json +++ b/package.json @@ -38,15 +38,14 @@ "@octokit/plugin-throttling": "^9.3.2", "@octokit/rest": "^20.0.2", "@octokit/webhooks": "^13.1.0", - "@sinclair/typebox": "^0.32.15", + "@sinclair/typebox": "^0.33.17", "@supabase/supabase-js": "2.43.1", - "@ubiquity-os/ubiquity-os-kernel": "^2.4.0", + "@ubiquity-os/ubiquity-os-kernel": "^2.5.1", "@ubiquity-os/ubiquity-os-logger": "^1.3.2", "commander": "12.0.0", "decimal.js": "^10.4.3", "dotenv": "^16.4.5", - "hono": "^4.6.5", - "typebox-validators": "0.3.5" + "hono": "^4.6.5" }, "devDependencies": { "@commitlint/cli": "^18.6.1", diff --git a/src/adapters/index.ts b/src/adapters/index.ts index ef7d6c9..941ac2c 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1,9 +1,9 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Access } from "./supabase/helpers/tables/access"; -import { User } from "./supabase/helpers/tables/user"; import { Label } from "./supabase/helpers/tables/label"; import { Super } from "./supabase/helpers/tables/super"; +import { User } from "./supabase/helpers/tables/user"; export function createAdapters(supabaseClient: SupabaseClient, context: Context) { return { diff --git a/src/adapters/supabase/helpers/tables/access.ts b/src/adapters/supabase/helpers/tables/access.ts index 6269fea..650c7af 100644 --- a/src/adapters/supabase/helpers/tables/access.ts +++ b/src/adapters/supabase/helpers/tables/access.ts @@ -1,5 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../../../../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; import { Super } from "./super"; diff --git a/src/adapters/supabase/helpers/tables/label.ts b/src/adapters/supabase/helpers/tables/label.ts index a5f48ee..6239e94 100644 --- a/src/adapters/supabase/helpers/tables/label.ts +++ b/src/adapters/supabase/helpers/tables/label.ts @@ -1,8 +1,8 @@ import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; import { Super } from "./super"; -import { Context } from "../../../../types/context"; type LabelRow = Database["public"]["Tables"]["labels"]["Row"]; diff --git a/src/adapters/supabase/helpers/tables/super.ts b/src/adapters/supabase/helpers/tables/super.ts index 662fb69..9bbaf81 100644 --- a/src/adapters/supabase/helpers/tables/super.ts +++ b/src/adapters/supabase/helpers/tables/super.ts @@ -1,5 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../../../../types/context"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Database } from "../../types/database"; export class Super { diff --git a/src/adapters/supabase/helpers/tables/user.ts b/src/adapters/supabase/helpers/tables/user.ts index b41130f..a4f52e2 100644 --- a/src/adapters/supabase/helpers/tables/user.ts +++ b/src/adapters/supabase/helpers/tables/user.ts @@ -1,6 +1,6 @@ import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { Super } from "./super"; -import { Context } from "../../../../types/context"; export class User extends Super { constructor(supabase: SupabaseClient, context: Context) { diff --git a/src/handlers/comment.ts b/src/handlers/comment.ts index bd07617..8528a14 100644 --- a/src/handlers/comment.ts +++ b/src/handlers/comment.ts @@ -1,9 +1,9 @@ import { addCommentToIssue, isUserAdminOrBillingManager } from "../shared/issue"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { isCommentEvent } from "../types/typeguards"; import commandParser, { AllowedCommand, CommandArguments, isValidCommand } from "./command-parser"; -const commandHandlers: { [k in AllowedCommand]: (context: Context, commandArguments: CommandArguments) => Promise } = { +const commandHandlers: { [k in AllowedCommand]: (context: ContextPlugin, commandArguments: CommandArguments) => Promise } = { async allow(context, { username, labels }: CommandArguments) { const logger = context.logger; if (!isCommentEvent(context)) { @@ -25,7 +25,7 @@ const commandHandlers: { [k in AllowedCommand]: (context: Context, commandArgume }, }; -export async function handleComment(context: Context) { +export async function handleComment(context: ContextPlugin) { const logger = context.logger; if (!isCommentEvent(context)) { return logger.debug("Not an comment event"); diff --git a/src/handlers/handle-parent-issue.ts b/src/handlers/handle-parent-issue.ts index 7fb2ff3..8e6dee9 100644 --- a/src/handlers/handle-parent-issue.ts +++ b/src/handlers/handle-parent-issue.ts @@ -1,9 +1,9 @@ import { clearAllPriceLabelsOnIssue } from "../shared/label"; import { calculateLabelValue } from "../shared/pricing"; -import { Context } from "../types/context"; import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; -export async function handleParentIssue(context: Context, labels: Label[]) { +export async function handleParentIssue(context: ContextPlugin, labels: Label[]) { const issuePrices = labels.filter((label) => label.name.toString().startsWith("Price:")); if (issuePrices.length) { await clearAllPriceLabelsOnIssue(context); diff --git a/src/handlers/label-change.ts b/src/handlers/label-change.ts index 1ffa6c6..b5d9d56 100644 --- a/src/handlers/label-change.ts +++ b/src/handlers/label-change.ts @@ -1,8 +1,8 @@ import { isUserAdminOrBillingManager } from "../shared/issue"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { isLabelEditedEvent } from "../types/typeguards"; -export async function watchLabelChange(context: Context) { +export async function watchLabelChange(context: ContextPlugin) { const logger = context.logger; if (!isLabelEditedEvent(context)) { logger.debug("Not a label event"); @@ -44,7 +44,7 @@ export async function watchLabelChange(context: Context) { return logger.debug("label name change saved to db"); } -async function hasLabelEditPermission(context: Context, label: string, caller: string) { +async function hasLabelEditPermission(context: ContextPlugin, label: string, caller: string) { const sufficientPrivileges = await isUserAdminOrBillingManager(context, caller); // get text before : diff --git a/src/handlers/pricing-label.ts b/src/handlers/pricing-label.ts index 1c6118c..82fe1e4 100644 --- a/src/handlers/pricing-label.ts +++ b/src/handlers/pricing-label.ts @@ -1,14 +1,12 @@ -import { Context } from "../types/context"; - import { addLabelToIssue, clearAllPriceLabelsOnIssue, createLabel, listLabelsForRepo, removeLabelFromIssue } from "../shared/label"; import { labelAccessPermissionsCheck } from "../shared/permissions"; import { Label, UserType } from "../types/github"; import { getPrice } from "../shared/pricing"; import { handleParentIssue, isParentIssue, sortLabelsByValue } from "./handle-parent-issue"; -import { AssistivePricingSettings } from "../types/plugin-input"; +import { AssistivePricingSettings, ContextPlugin } from "../types/plugin-input"; import { isIssueLabelEvent } from "../types/typeguards"; -export async function onLabelChangeSetPricing(context: Context): Promise { +export async function onLabelChangeSetPricing(context: ContextPlugin): Promise { if (!isIssueLabelEvent(context)) { context.logger.debug("Not an issue event"); return; @@ -50,7 +48,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { const smallestPriceLabelName = smallestPriceLabel?.name; if (smallestPriceLabelName) { for (const label of sortedPriceLabels) { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner, repo: payload.repository.name, issue_number: payload.issue.number, @@ -65,7 +63,7 @@ export async function onLabelChangeSetPricing(context: Context): Promise { await setPriceLabel(context, labels, config); } -export async function setPriceLabel(context: Context, issueLabels: Label[], config: AssistivePricingSettings) { +export async function setPriceLabel(context: ContextPlugin, issueLabels: Label[], config: AssistivePricingSettings) { const logger = context.logger; const labelNames = issueLabels.map((i) => i.name); @@ -121,7 +119,7 @@ function getMinLabels(recognizedLabels: { time: Label[]; priority: Label[] }) { return { time: minTimeLabel, priority: minPriorityLabel }; } -async function handleTargetPriceLabel(context: Context, targetPriceLabel: string, labelNames: string[]) { +async function handleTargetPriceLabel(context: ContextPlugin, targetPriceLabel: string, labelNames: string[]) { const { repository } = context.payload; if (repository.name === "devpool-directory") { targetPriceLabel = targetPriceLabel.replace("Price: ", "Pricing: "); @@ -139,7 +137,7 @@ async function handleTargetPriceLabel(context: Context, targetPriceLabel: string } } -async function handleExistingPriceLabel(context: Context, targetPriceLabel: string) { +async function handleExistingPriceLabel(context: ContextPlugin, targetPriceLabel: string) { const logger = context.logger; let labeledEvents = await getAllLabeledEvents(context); if (!labeledEvents) return logger.error("No labeled events found"); @@ -154,25 +152,25 @@ async function handleExistingPriceLabel(context: Context, targetPriceLabel: stri } } -async function addPriceLabelToIssue(context: Context, targetPriceLabel: string) { +async function addPriceLabelToIssue(context: ContextPlugin, targetPriceLabel: string) { await clearAllPriceLabelsOnIssue(context); await addLabelToIssue(context, targetPriceLabel); } -async function getAllLabeledEvents(context: Context) { +async function getAllLabeledEvents(context: ContextPlugin) { const events = await getAllIssueEvents(context); if (!events) return null; return events.filter((event) => event.event === "labeled"); } -async function getAllIssueEvents(context: Context) { +async function getAllIssueEvents(context: ContextPlugin) { if (!("issue" in context.payload) || !context.payload.issue) { context.logger.debug("Not an issue event"); return; } try { - return await context.octokit.paginate(context.octokit.issues.listEvents, { + return await context.octokit.paginate(context.octokit.rest.issues.listEvents, { owner: context.payload.repository.owner.login, repo: context.payload.repository.name, issue_number: context.payload.issue.number, diff --git a/src/handlers/sync-labels-to-config.ts b/src/handlers/sync-labels-to-config.ts index 61d81a2..2684a70 100644 --- a/src/handlers/sync-labels-to-config.ts +++ b/src/handlers/sync-labels-to-config.ts @@ -1,13 +1,13 @@ import { Logs } from "@ubiquity-os/ubiquity-os-logger"; import { COLORS, createLabel, listLabelsForRepo } from "../shared/label"; import { calculateLabelValue, calculateTaskPrice } from "../shared/pricing"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { Label } from "../types/github"; // This just checks all the labels in the config have been set in gh issue // If there's something missing, they will be added -export async function syncPriceLabelsToConfig(context: Context): Promise { +export async function syncPriceLabelsToConfig(context: ContextPlugin): Promise { const { config, logger } = context; const priceLabels: string[] = []; diff --git a/src/index.ts b/src/index.ts index 83dd394..80fd386 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,41 +1,21 @@ -import * as github from "@actions/github"; -import * as core from "@actions/core"; -import { Value } from "@sinclair/typebox/value"; -import { envSchema } from "./types/env"; -import { pluginSettingsSchema, PluginInputs } from "./types/plugin-input"; +import { createClient } from "@supabase/supabase-js"; +import { createActionsPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import { LogLevel } from "@ubiquity-os/ubiquity-os-logger"; +import { createAdapters } from "./adapters"; import { run } from "./run"; -import { returnDataToKernel } from "./handlers/return-data-to-kernel"; +import { SupportedEvents } from "./types/context"; +import { Env, envSchema } from "./types/env"; +import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; -/** - * Run the plugin as a GitHub Action instance. - */ -async function actionRun() { - const payloadEnv = { - SUPABASE_KEY: process.env.SUPABASE_KEY, - SUPABASE_URL: process.env.SUPABASE_URL, - }; - - const env = Value.Decode(envSchema, payloadEnv); - - const webhookPayload = github.context.payload.inputs; - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(webhookPayload.settings))); - - const inputs: PluginInputs = { - stateId: webhookPayload.stateId, - eventName: webhookPayload.eventName, - eventPayload: JSON.parse(webhookPayload.eventPayload), - settings: settings, - authToken: webhookPayload.authToken, - ref: webhookPayload.ref, - }; - await run(inputs, env); - - return await returnDataToKernel(inputs.authToken, inputs.stateId, {}); -} - -actionRun() - .then((result) => core.setOutput("result", result)) - .catch((error) => { - console.error(error); - core.setFailed(error); - }); +createActionsPlugin( + (context) => { + return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); + }, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: process.env.LOG_LEVEL as LogLevel, + kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, + } +).catch(console.error); diff --git a/src/run.ts b/src/run.ts index 67f8b41..05f1d6a 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,33 +1,14 @@ -import { Octokit } from "@octokit/rest"; -import { createClient } from "@supabase/supabase-js"; -import { createAdapters } from "./adapters"; import { handleComment } from "./handlers/comment"; import { watchLabelChange } from "./handlers/label-change"; import { onLabelChangeSetPricing } from "./handlers/pricing-label"; import { syncPriceLabelsToConfig } from "./handlers/sync-labels-to-config"; -import { Context } from "./types/context"; -import { Env } from "./types/env"; -import { PluginInputs } from "./types/plugin-input"; +import { ContextPlugin } from "./types/plugin-input"; import { globalLabelUpdate } from "./handlers/global-config-update"; import { isIssueLabelEvent } from "./types/typeguards"; -import { Logs } from "@ubiquity-os/ubiquity-os-logger"; -export async function run(inputs: PluginInputs, env: Env) { - const octokit = new Octokit({ auth: inputs.authToken }); - const supabaseClient = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); +export async function run(context: ContextPlugin) { + const { eventName, logger } = context; - const context: Context = { - eventName: inputs.eventName, - payload: inputs.eventPayload, - config: inputs.settings, - octokit, - logger: new Logs("info"), - adapters: {} as ReturnType, - env, - }; - context.adapters = createAdapters(supabaseClient, context); - - const eventName = inputs.eventName; switch (eventName) { case "issues.opened": case "repository.created": @@ -50,6 +31,7 @@ export async function run(inputs: PluginInputs, env: Env) { await globalLabelUpdate(context); break; default: - context.logger.error(`Event ${eventName} is not supported`); + logger.error(`Event ${eventName} is not supported`); } + return { message: "OK" }; } diff --git a/src/shared/issue.ts b/src/shared/issue.ts index 47df0da..7da8914 100644 --- a/src/shared/issue.ts +++ b/src/shared/issue.ts @@ -1,6 +1,6 @@ -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; -async function checkIfIsAdmin(context: Context, username: string) { +async function checkIfIsAdmin(context: ContextPlugin, username: string) { const owner = context.payload.repository.owner?.login; if (!owner) throw context.logger.error("No owner found in the repository!"); const response = await context.octokit.rest.repos.getCollaboratorPermissionLevel({ @@ -11,7 +11,7 @@ async function checkIfIsAdmin(context: Context, username: string) { return response.data.permission === "admin"; } -async function checkIfIsBillingManager(context: Context, username: string) { +async function checkIfIsBillingManager(context: ContextPlugin, username: string) { if (!context.payload.organization) throw context.logger.error(`No organization found in payload!`); try { @@ -30,7 +30,7 @@ async function checkIfIsBillingManager(context: Context, username: string) { return membership.role === "billing_manager"; } -export async function isUserAdminOrBillingManager(context: Context, username?: string): Promise<"admin" | "billing_manager" | false> { +export async function isUserAdminOrBillingManager(context: ContextPlugin, username?: string): Promise<"admin" | "billing_manager" | false> { if (!username) return false; const isAdmin = await checkIfIsAdmin(context, username); if (isAdmin) return "admin"; @@ -41,13 +41,13 @@ export async function isUserAdminOrBillingManager(context: Context, username?: s return false; } -export async function addCommentToIssue(context: Context, message: string, issueNumber: number, repoOwner?: string, repo?: string) { +export async function addCommentToIssue(context: ContextPlugin, message: string, issueNumber: number, repoOwner?: string, repo?: string) { const payload = context.payload; const owner = repoOwner || payload.repository.owner?.login; if (!owner) throw context.logger.error("No owner found in the repository!"); try { - await context.octokit.issues.createComment({ + await context.octokit.rest.issues.createComment({ owner, repo: repo ?? payload.repository.name, issue_number: issueNumber, @@ -58,7 +58,7 @@ export async function addCommentToIssue(context: Context, message: string, issue } } -export async function listOrgRepos(context: Context) { +export async function listOrgRepos(context: ContextPlugin) { const org = context.payload.organization?.login; if (!org) throw context.logger.error("No organization found in payload!"); @@ -72,7 +72,7 @@ export async function listOrgRepos(context: Context) { } } -export async function listRepoIssues(context: Context, owner: string, repo: string) { +export async function listRepoIssues(context: ContextPlugin, owner: string, repo: string) { try { const response = await context.octokit.rest.issues.listForRepo({ owner, diff --git a/src/shared/label.ts b/src/shared/label.ts index fd91d36..39646b6 100644 --- a/src/shared/label.ts +++ b/src/shared/label.ts @@ -1,5 +1,5 @@ -import { Context } from "../types/context"; import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; // cspell:disable export const COLORS = { default: "ededed", price: "1f883d" }; @@ -7,7 +7,7 @@ export const COLORS = { default: "ededed", price: "1f883d" }; const NO_REPO_OWNER = "No owner found in the repository!"; -export async function listLabelsForRepo(context: Context): Promise { +export async function listLabelsForRepo(context: ContextPlugin): Promise { const { payload, octokit } = context; const owner = payload.repository.owner?.login; @@ -31,7 +31,7 @@ export async function listLabelsForRepo(context: Context): Promise { throw context.logger.error("Failed to fetch lists of labels", { status: 500 }); } -export async function createLabel(context: Context, name: string, labelType = "default" as keyof typeof COLORS): Promise { +export async function createLabel(context: ContextPlugin, name: string, labelType = "default" as keyof typeof COLORS): Promise { const payload = context.payload; const color = name.startsWith("Price: ") ? COLORS.price : COLORS[labelType]; @@ -52,7 +52,7 @@ export async function createLabel(context: Context, name: string, labelType = "d } } -export async function clearAllPriceLabelsOnIssue(context: Context) { +export async function clearAllPriceLabelsOnIssue(context: ContextPlugin) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; @@ -65,7 +65,7 @@ export async function clearAllPriceLabelsOnIssue(context: Context) { for (const label of issuePriceLabels) { try { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, @@ -76,14 +76,14 @@ export async function clearAllPriceLabelsOnIssue(context: Context) { } } } -export async function addLabelToIssue(context: Context, labelName: string) { +export async function addLabelToIssue(context: ContextPlugin, labelName: string) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; } try { - await context.octokit.issues.addLabels({ + await context.octokit.rest.issues.addLabels({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, @@ -94,14 +94,14 @@ export async function addLabelToIssue(context: Context, labelName: string) { } } -export async function removeLabelFromIssue(context: Context, labelName: string) { +export async function removeLabelFromIssue(context: ContextPlugin, labelName: string) { const payload = context.payload; if (!("issue" in payload) || !payload.issue) { return; } try { - await context.octokit.issues.removeLabel({ + await context.octokit.rest.issues.removeLabel({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.issue.number, diff --git a/src/shared/permissions.ts b/src/shared/permissions.ts index 9baaee3..e9ba65d 100644 --- a/src/shared/permissions.ts +++ b/src/shared/permissions.ts @@ -1,10 +1,10 @@ -import { Context } from "../types/context"; import { UserType } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; import { isIssueLabelEvent } from "../types/typeguards"; import { addCommentToIssue, isUserAdminOrBillingManager } from "./issue"; import { addLabelToIssue, removeLabelFromIssue } from "./label"; -export async function labelAccessPermissionsCheck(context: Context) { +export async function labelAccessPermissionsCheck(context: ContextPlugin) { if (!isIssueLabelEvent(context)) { context.logger.debug("Not an issue event"); return; diff --git a/src/shared/pricing.ts b/src/shared/pricing.ts index a0a790d..2018a55 100644 --- a/src/shared/pricing.ts +++ b/src/shared/pricing.ts @@ -1,14 +1,14 @@ -import { Context } from "../types/context"; -import { Label } from "../types/github"; import { Decimal } from "decimal.js"; +import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; -export function calculateTaskPrice(context: Context, timeValue: number, priorityValue: number, baseValue?: number): string { +export function calculateTaskPrice(context: ContextPlugin, timeValue: number, priorityValue: number, baseValue?: number): string { const base = baseValue ?? context.config.basePriceMultiplier; const priority = new Decimal(priorityValue).div(10); // floats cause bad math return new Decimal(base).mul(1000).mul(timeValue).mul(priority).toDecimalPlaces(2).toString(); } -export function getPrice(context: Context, timeLabel: Label, priorityLabel: Label) { +export function getPrice(context: ContextPlugin, timeLabel: Label, priorityLabel: Label) { const logger = context.logger; const { labels } = context.config; diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 7da4600..73acabc 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -1,7 +1,10 @@ import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks"; +import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { Context } from "@ubiquity-os/ubiquity-os-kernel"; import { StandardValidator } from "typebox-validators"; +import { createAdapters } from "../adapters"; import { SupportedEvents } from "./context"; -import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { Env } from "./env"; export interface PluginInputs { stateId: string; @@ -45,3 +48,5 @@ export type Rates = { previousBaseRate: number | null; newBaseRate: number | null; }; + +export type ContextPlugin = Context & { adapters: ReturnType }; diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 6e50cd3..ce273dc 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,12 +1,13 @@ import { Context } from "./context"; +import { ContextPlugin } from "./plugin-input"; export function isCommentEvent( - context: Context -): context is Context & { payload: { issue: Context<"issue_comment">["payload"]["issue"]; comment: Context<"issue_comment">["payload"]["comment"] } } { + context: ContextPlugin +): context is ContextPlugin & { payload: { issue: Context<"issue_comment">["payload"]["issue"]; comment: Context<"issue_comment">["payload"]["comment"] } } { return context.eventName.startsWith("issue_comment."); } -export function isIssueLabelEvent(context: Context): context is Context & { +export function isIssueLabelEvent(context: ContextPlugin): context is ContextPlugin & { payload: { issue: Context<"issues.labeled" | "issues.unlabeled">["payload"]["issue"]; label: Context<"issues.labeled" | "issues.unlabeled">["payload"]["label"]; @@ -19,7 +20,7 @@ export function isPushEvent(context: Context): context is Context & { payload: C return context.eventName === "push"; } -export function isLabelEditedEvent(context: Context): context is Context & { +export function isLabelEditedEvent(context: ContextPlugin): context is ContextPlugin & { payload: { label: Context<"label.edited">["payload"]["label"]; changes: Context<"label.edited">["payload"]["changes"]; diff --git a/src/worker.ts b/src/worker.ts index 93a5a3d..3852a86 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,51 +1,23 @@ -import manifest from "../manifest.json"; -import { validateAndDecodeSchemas } from "./handlers/validator"; +import { createClient } from "@supabase/supabase-js"; +import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import { createAdapters } from "./adapters"; import { run } from "./run"; -import { Env } from "./types/env"; - -export default { - async fetch(request: Request, env: Env): Promise { - try { - const url = new URL(request.url); - if (url.pathname === "/manifest.json" && request.method === "GET") { - return new Response(JSON.stringify(manifest), { - headers: { "content-type": "application/json" }, - }); - } else if (url.pathname === "/manifest.json" && 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") { - return new Response(JSON.stringify({ error: `Only POST requests are supported.` }), { - status: 405, - headers: { "content-type": "application/json", Allow: "POST" }, - }); - } - const contentType = request.headers.get("content-type"); - if (contentType !== "application/json") { - return new Response(JSON.stringify({ error: `Bad request: ${contentType} is not a valid content type` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - - const webhookPayload = await request.json(); - const { decodedSettings, decodedEnv } = validateAndDecodeSchemas(env, webhookPayload.settings); +import { SupportedEvents } from "./types/context"; +import { Env, envSchema } from "./types/env"; +import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; +import manifest from "../manifest.json"; - webhookPayload.env = decodedEnv; - webhookPayload.settings = decodedSettings; - await run(webhookPayload, decodedEnv); - return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } }); - } catch (error) { - return handleUncaughtError(error); - } +export default createPlugin( + (context) => { + return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); }, -}; - -function handleUncaughtError(errors: unknown) { - console.error(errors); - const status = 500; - return new Response(JSON.stringify(errors), { status: status, headers: { "content-type": "application/json" } }); -} + //@ts-expect-error types are ok + manifest, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: process.env.LOG_LEVEL, + kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, + } +); diff --git a/tests/main.test.ts b/tests/main.test.ts index e18ab8e..87ad4ad 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -1,7 +1,9 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; import { drop } from "@mswjs/data"; +import * as crypto from "crypto"; import commandParser, { CommandArguments } from "../src/handlers/command-parser"; import { Env } from "../src/types/env"; +import { ContextPlugin } from "../src/types/plugin-input"; import workerFetch from "../src/worker"; import { db } from "./__mocks__/db"; import { server } from "./__mocks__/node"; @@ -11,7 +13,6 @@ import * as crypto from "crypto"; import { AssistivePricingSettings, pluginSettingsSchema } from "../src/types/plugin-input"; import { Value } from "@sinclair/typebox/value"; import { calculateLabelValue, calculateTaskPrice } from "../src/shared/pricing"; -import { Context } from "../src/types/context"; const { privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048, @@ -131,7 +132,7 @@ describe("User tests", () => { }, ]; for (const testCase of testCases) { - const price = calculateTaskPrice(context as unknown as Context, testCase.timeValue, testCase.priorityValue); + const price = calculateTaskPrice(context as unknown as ContextPlugin, testCase.timeValue, testCase.priorityValue); expect(price).toEqual(testCase.expectedPrice); } }); From 7ee03ee4a391d3e51708417c079fef561b0e013b Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:55:03 +0900 Subject: [PATCH 12/22] fix: support ESM and update configurations Added ESM support in Jest and package.json, updated moduleResolution in tsconfig. --- jest.config.ts | 12 ++++++++++++ package.json | 1 + src/types/env.ts | 4 ---- src/types/plugin-input.ts | 13 ------------- tests/main.test.ts | 4 ++-- tsconfig.json | 2 +- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index a6555b0..5bb35e7 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -9,4 +9,16 @@ module.exports = { coverageReporters: ["json", "lcov", "text", "clover", "json-summary"], reporters: ["default", "jest-junit", "jest-md-dashboard"], coverageDirectory: "coverage", + extensionsToTreatAsEsm: [".ts"], + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1", + }, + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true, + }, + ], + }, } as JestConfigWithTsJest; diff --git a/package.json b/package.json index 3004965..2276085 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "engines": { "node": ">=20.10.0" }, + "type": "module", "scripts": { "worker": "wrangler dev --env dev --port 4000", "start": "tsx src/index.ts", diff --git a/src/types/env.ts b/src/types/env.ts index fe18b8f..4f796ec 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -1,12 +1,8 @@ import { StaticDecode, Type as T } from "@sinclair/typebox"; -import "dotenv/config"; -import { StandardValidator } from "typebox-validators"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), }); -export const envConfigValidator = new StandardValidator(envSchema); - export type Env = StaticDecode; diff --git a/src/types/plugin-input.ts b/src/types/plugin-input.ts index 73acabc..9ec551a 100644 --- a/src/types/plugin-input.ts +++ b/src/types/plugin-input.ts @@ -1,20 +1,9 @@ -import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as WebhookEventName } from "@octokit/webhooks"; import { StaticDecode, Type as T } from "@sinclair/typebox"; import { Context } from "@ubiquity-os/ubiquity-os-kernel"; -import { StandardValidator } from "typebox-validators"; import { createAdapters } from "../adapters"; import { SupportedEvents } from "./context"; import { Env } from "./env"; -export interface PluginInputs { - stateId: string; - eventName: T; - eventPayload: WebhookEvent["payload"]; - settings: AssistivePricingSettings; - authToken: string; - ref: string; -} - export const pluginSettingsSchema = T.Object( { globalConfigUpdate: T.Optional( @@ -41,8 +30,6 @@ export const pluginSettingsSchema = T.Object( { default: {} } ); -export const assistivePricingSchemaValidator = new StandardValidator(pluginSettingsSchema); - export type AssistivePricingSettings = StaticDecode; export type Rates = { previousBaseRate: number | null; diff --git a/tests/main.test.ts b/tests/main.test.ts index 87ad4ad..d041504 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -1,4 +1,4 @@ -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { drop } from "@mswjs/data"; import * as crypto from "crypto"; import commandParser, { CommandArguments } from "../src/handlers/command-parser"; @@ -26,7 +26,7 @@ const { privateKey } = crypto.generateKeyPairSync("rsa", { }, }); -const url = "http://localhost:4000"; +const url = "/"; beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); diff --git a/tsconfig.json b/tsconfig.json index c6d3097..8c39d70 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,7 @@ /* Modules */ "module": "commonjs" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ From 47c5b0167d2f0b8a04a287f4cb5bf67eaa7b25a0 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 21:59:33 +0900 Subject: [PATCH 13/22] chore: remove validator and update test script Deleted `validator.ts`, removed unused dependencies, and updated the test script in `package.json`. --- package.json | 4 +--- src/handlers/validator.ts | 35 ----------------------------------- yarn.lock | 4 ++-- 3 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 src/handlers/validator.ts diff --git a/package.json b/package.json index 2276085..125e7e1 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "knip": "knip --config .github/knip.ts", "knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts", "prepare": "husky install", - "test": "jest --setupFiles dotenv/config --coverage", + "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --setupFiles dotenv/config --coverage", "supabase:generate:local": "supabase gen types typescript --local > src/adapters/supabase/types/database.ts", "supabase:generate:remote": "dotenv -- cross-env-shell supabase gen types typescript --project-id $SUPABASE_PROJECT_ID --schema public > src/adapters/supabase/types/database.ts" }, @@ -32,8 +32,6 @@ "open-source" ], "dependencies": { - "@actions/core": "^1.10.1", - "@actions/github": "^6.0.0", "@commander-js/extra-typings": "12.0.1", "@octokit/plugin-retry": "^7.1.2", "@octokit/plugin-throttling": "^9.3.2", diff --git a/src/handlers/validator.ts b/src/handlers/validator.ts deleted file mode 100644 index f2f96c3..0000000 --- a/src/handlers/validator.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { TransformDecodeCheckError, TransformDecodeError, Value, ValueError } from "@sinclair/typebox/value"; -import { Env, envConfigValidator, envSchema } from "../types/env"; -import { assistivePricingSchemaValidator, AssistivePricingSettings, pluginSettingsSchema } from "../types/plugin-input"; - -export function validateAndDecodeSchemas(env: Env, rawSettings: object) { - const errors: ValueError[] = []; - const settings = Value.Default(pluginSettingsSchema, rawSettings) as AssistivePricingSettings; - - if (!assistivePricingSchemaValidator.test(settings)) { - for (const error of assistivePricingSchemaValidator.errors(settings)) { - errors.push(error); - } - } - - if (!envConfigValidator.test(env)) { - for (const error of envConfigValidator.errors(env)) { - errors.push(error); - } - } - - if (errors.length) { - throw { errors }; - } - - try { - const decodedEnv = Value.Decode(envSchema, 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/yarn.lock b/yarn.lock index 3f0d6ed..7f5a81d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@actions/core@1.10.1", "@actions/core@^1.10.1": +"@actions/core@1.10.1": version "1.10.1" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a" integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g== @@ -15,7 +15,7 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" -"@actions/github@6.0.0", "@actions/github@^6.0.0": +"@actions/github@6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.0.tgz#65883433f9d81521b782a64cc1fd45eef2191ea7" integrity sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g== From 0b87880484a94ee482f735c67c8f7475def53b04 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:09:06 +0900 Subject: [PATCH 14/22] test: update URL and adjust expectations in test case Update the URL in the fetch call and modify the expected response status and `ok` flag. --- tests/main.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/main.test.ts b/tests/main.test.ts index d041504..bcf9625 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -171,15 +171,15 @@ describe("User tests", () => { const result = await workerFetch.fetch( { method: "GET", - url, + url: `${url}/manifest.json`, } as unknown as Request, { SUPABASE_URL: "url", SUPABASE_KEY: "key", } ); - expect(result.ok).toEqual(false); - expect(result.status).toEqual(405); + expect(result.ok).toEqual(true); + expect(result.status).toEqual(200); }); it("Should reject an invalid environment", async () => { From 7762c976698f11b5dac64c03d0f9a25a69f5f242 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:21:19 +0900 Subject: [PATCH 15/22] test: correct stateId and user login in mock JSON file Updated `stateId` in `issue-comment-post.json --- .../requests/issue-comment-post.json | 3 ++- tests/main.test.ts | 26 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/__mocks__/requests/issue-comment-post.json b/tests/__mocks__/requests/issue-comment-post.json index 6ff490c..63c9ebe 100644 --- a/tests/__mocks__/requests/issue-comment-post.json +++ b/tests/__mocks__/requests/issue-comment-post.json @@ -1,5 +1,5 @@ { - "stateId": "", + "stateId": "1234", "eventName": "issue_comment.created", "eventPayload": { "action": "created", @@ -15,6 +15,7 @@ "number": 5, "title": "New issue", "user": { + "login": "gentlementlegen", "login": "gentlementlegen", "id": 9807008, "node_id": "MDQ6VXNlcjk4MDcwMDg=", diff --git a/tests/main.test.ts b/tests/main.test.ts index bcf9625..91e45d6 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -138,10 +138,7 @@ describe("User tests", () => { }); it("Should handle the comment", async () => { - const data = { - ...issueCommented, - authToken: process.env.GITHUB_TOKEN, - }; + const data = issueCommented; const sign = crypto.createSign("SHA256"); sign.update(JSON.stringify(data)); sign.end(); @@ -171,19 +168,23 @@ describe("User tests", () => { const result = await workerFetch.fetch( { method: "GET", - url: `${url}/manifest.json`, + url, } as unknown as Request, { SUPABASE_URL: "url", SUPABASE_KEY: "key", } ); - expect(result.ok).toEqual(true); - expect(result.status).toEqual(200); + expect(result.ok).toEqual(false); + expect(result.status).toEqual(404); }); it("Should reject an invalid environment", async () => { - const errorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); + const data = issueCommented; + const sign = crypto.createSign("SHA256"); + sign.update(JSON.stringify(data)); + sign.end(); + const signature = sign.sign(privateKey, "base64"); const result = await workerFetch.fetch( { method: "POST", @@ -191,9 +192,10 @@ describe("User tests", () => { get: () => "application/json", }, url: undefined, - json() { - return { settings: {} }; - }, + json: () => ({ + ...data, + signature, + }), } as unknown as Request, { SUPABASE_URL: "url", @@ -201,7 +203,7 @@ describe("User tests", () => { } as unknown as Env ); expect(result.ok).toEqual(false); - expect(result.status).toEqual(500); + expect(result.status).toEqual(400); expect(errorSpy).toHaveBeenCalled(); }); }); From cb6b24e8fef4ed8fcbe1bc010bbd6fc4f100c2f5 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:45:41 +0900 Subject: [PATCH 16/22] chore: integrate fetch handler with createPlugin method Enhanced plugin setup by adding fetch handler to handle requests --- .cspell.json | 2 +- src/types/env.ts | 4 +++ src/worker.ts | 34 ++++++++++++------- .../requests/issue-comment-post.json | 1 - 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.cspell.json b/.cspell.json index 04c71a4..eb6fe0d 100644 --- a/.cspell.json +++ b/.cspell.json @@ -29,7 +29,7 @@ "typeguards", "mswjs", "ubiquity-os" - ], + , "hono"], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/src/types/env.ts b/src/types/env.ts index 4f796ec..e5383cc 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -1,8 +1,12 @@ import { StaticDecode, Type as T } from "@sinclair/typebox"; +import { LOG_LEVEL } from "@ubiquity-os/ubiquity-os-logger"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), + UBIQUIBOT_PUBLIC_KEY: T.String(), + LOG_LEVEL: T.Optional(T.Enum(LOG_LEVEL)), + KERNEL_PUBLIC_KEY: T.Optional(T.String()), }); export type Env = StaticDecode; diff --git a/src/worker.ts b/src/worker.ts index 3852a86..3946d65 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,5 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; +import type { ExecutionContext } from "hono/dist/types/context"; import { createAdapters } from "./adapters"; import { run } from "./run"; import { SupportedEvents } from "./types/context"; @@ -7,17 +8,24 @@ import { Env, envSchema } from "./types/env"; import { AssistivePricingSettings, pluginSettingsSchema } from "./types/plugin-input"; import manifest from "../manifest.json"; -export default createPlugin( - (context) => { - return run({ ...context, adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context) }); +export default { + async fetch(request: Request, env: Env, executionCtx?: ExecutionContext) { + return createPlugin( + (context) => { + return run({ + ...context, + adapters: createAdapters(createClient(context.env.SUPABASE_URL, context.env.SUPABASE_KEY), context), + }); + }, + //@ts-expect-error types are ok + manifest, + { + envSchema: envSchema, + postCommentOnError: true, + settingsSchema: pluginSettingsSchema, + logLevel: env.LOG_LEVEL, + kernelPublicKey: env.KERNEL_PUBLIC_KEY, + } + ).fetch(request, env, executionCtx); }, - //@ts-expect-error types are ok - manifest, - { - envSchema: envSchema, - postCommentOnError: true, - settingsSchema: pluginSettingsSchema, - logLevel: process.env.LOG_LEVEL, - kernelPublicKey: process.env.KERNEL_PUBLIC_KEY, - } -); +}; diff --git a/tests/__mocks__/requests/issue-comment-post.json b/tests/__mocks__/requests/issue-comment-post.json index 63c9ebe..fdbb2ec 100644 --- a/tests/__mocks__/requests/issue-comment-post.json +++ b/tests/__mocks__/requests/issue-comment-post.json @@ -15,7 +15,6 @@ "number": 5, "title": "New issue", "user": { - "login": "gentlementlegen", "login": "gentlementlegen", "id": 9807008, "node_id": "MDQ6VXNlcjk4MDcwMDg=", From fc824fae34cd3cb167f3427ca113c780e0b661fa Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:47:54 +0900 Subject: [PATCH 17/22] chore: update import for ExecutionContext Simplify type import for ExecutionContext from 'hono' package. --- src/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/worker.ts b/src/worker.ts index 3946d65..5720630 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,6 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import { createPlugin } from "@ubiquity-os/ubiquity-os-kernel"; -import type { ExecutionContext } from "hono/dist/types/context"; +import type { ExecutionContext } from "hono"; import { createAdapters } from "./adapters"; import { run } from "./run"; import { SupportedEvents } from "./types/context"; From f9bc0842ed75c82e8b915590f28af16dec39b8a5 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Mon, 28 Oct 2024 22:49:50 +0900 Subject: [PATCH 18/22] chore(package): add Hono framework dependency Added Hono framework version 4.6.7 to project dependencies in package.json and updated yarn.lock. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 125e7e1..04f1e54 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "commander": "12.0.0", "decimal.js": "^10.4.3", "dotenv": "^16.4.5", - "hono": "^4.6.5" + "hono": "^4.6.7" }, "devDependencies": { "@commitlint/cli": "^18.6.1", From 6c7347ff520ca9901ea9498d293e875682fd1881 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 00:51:57 +0900 Subject: [PATCH 19/22] chore: update dependencies and configuration Updated wrangler settings, updated to latest package versions. --- package.json | 2 +- wrangler.toml | 3 ++ yarn.lock | 122 +++++++++++++++++++++++++++----------------------- 3 files changed, 71 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index 04f1e54..086e141 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "ts-node": "10.9.2", "tsx": "^4.7.1", "typescript": "5.6.2", - "wrangler": "3.79.0" + "wrangler": "^3.83.0" }, "lint-staged": { "*.ts": [ diff --git a/wrangler.toml b/wrangler.toml index 96f8ec8..469c0ed 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -4,3 +4,6 @@ compatibility_date = "2024-09-23" compatibility_flags = [ "nodejs_compat" ] [env.dev] [env.prod] + +[observability] +enabled = true \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7f5a81d..19c1472 100644 --- a/yarn.lock +++ b/yarn.lock @@ -361,35 +361,35 @@ dependencies: mime "^3.0.0" -"@cloudflare/workerd-darwin-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240925.0.tgz#f78fe394f73540594609d8e05a2da7feb46c76c0" - integrity sha512-KdLnSXuzB65CbqZPm+qYzk+zkQ1tUNPaaRGYVd/jPYAxwwtfTUQdQ+ahDPwVVs2tmQELKy7ZjQjf2apqSWUfjw== - -"@cloudflare/workerd-darwin-arm64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240925.0.tgz#f03b17177744ad898bb12610d15cc0a9744abfe6" - integrity sha512-MiQ6uUmCXjsXgWNV+Ock2tp2/tYqNJGzjuaH6jFioeRF+//mz7Tv7J7EczOL4zq+TH8QFOh0/PUsLyazIWVGng== - -"@cloudflare/workerd-linux-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240925.0.tgz#fe0366b804b957acf5012d889e94163bab806a57" - integrity sha512-Rjix8jsJMfsInmq3Hm3fmiRQ+rwzuWRPV1pg/OWhMSfNP7Qp2RCU+RGkhgeR9Z5eNAje0Sn2BMrFq4RvF9/yRA== - -"@cloudflare/workerd-linux-arm64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240925.0.tgz#fcf82de06def420972c661a6021c87683cd8fbdc" - integrity sha512-VYIPeMHQRtbwQoIjUwS/zULlywPxyDvo46XkTpIW5MScEChfqHvAYviQ7TzYGx6Q+gmZmN+DUB2KOMx+MEpCxA== - -"@cloudflare/workerd-windows-64@1.20240925.0": - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240925.0.tgz#0a5c82b95b03a94591cc8a1830f28d2e41ff7685" - integrity sha512-C8peGvaU5R51bIySi1VbyfRgwNSSRknqoFSnSbSBI3uTN3THTB3UnmRKy7GXJDmyjgXuT9Pcs1IgaWNubLtNtw== - -"@cloudflare/workers-shared@0.5.4": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.5.4.tgz#bbf8f03b79a6bc0169ad66a6015ebe579d36753a" - integrity sha512-PNL/0TjKRdUHa1kwgVdqUNJVZ9ez4kacsi8omz+gv859EvJmsVuGiMAClY2YfJnC9LVKhKCcjqmFgKNXG9/IXA== +"@cloudflare/workerd-darwin-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241022.0.tgz#1d22149152ad32672971e3be48ab1491ff236eb3" + integrity sha512-1NNYun37myMTgCUiPQEJ0cMal4mKZVTpkD0b2tx9hV70xji+frVJcSK8YVLeUm1P+Rw1d/ct8DMgQuCpsz3Fsw== + +"@cloudflare/workerd-darwin-arm64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241022.0.tgz#6ec4e4fd1427ac09d9cfea38db849799755029e5" + integrity sha512-FOO/0P0U82EsTLTdweNVgw+4VOk5nghExLPLSppdOziq6IR5HVgP44Kmq5LdsUeHUhwUmfOh9hzaTpkNzUqKvw== + +"@cloudflare/workerd-linux-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241022.0.tgz#0297222e46ce8b2c55b591ae87ee2bbb85830e20" + integrity sha512-RsNc19BQJG9yd+ngnjuDeG9ywZG+7t1L4JeglgceyY5ViMNMKVO7Zpbsu69kXslU9h6xyQG+lrmclg3cBpnhYA== + +"@cloudflare/workerd-linux-arm64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241022.0.tgz#7637092b14129c94ddb87990221d38623e4fd498" + integrity sha512-x5mUXpKxfsosxcFmcq5DaqLs37PejHYVRsNz1cWI59ma7aC4y4Qn6Tf3i0r9MwQTF/MccP4SjVslMU6m4W7IaA== + +"@cloudflare/workerd-windows-64@1.20241022.0": + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241022.0.tgz#64f05a2bc475e1450154942c060555184e6350de" + integrity sha512-eBCClx4szCOgKqOlxxbdNszMqQf3MRG1B9BRIqEM/diDfdR9IrZ8l3FaEm+l9gXgPmS6m1NBn40aWuGBl8UTSw== + +"@cloudflare/workers-shared@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.7.0.tgz#ecb6a3a1f483989c1ca10d5ed0592d01c7eff0c0" + integrity sha512-LLQRTqx7lKC7o2eCYMpyc5FXV8d0pUX6r3A+agzhqS9aoR5A6zCPefwQGcvbKx83ozX22ATZcemwxQXn12UofQ== dependencies: mime "^3.0.0" zod "^3.22.3" @@ -3505,6 +3505,11 @@ date-fns@^2.21.1: dependencies: "@babel/runtime" "^7.21.0" +date-fns@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" + integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== + debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -4945,6 +4950,11 @@ iterable-lookahead@^1.0.0: resolved "https://registry.yarnpkg.com/iterable-lookahead/-/iterable-lookahead-1.0.0.tgz#896dfcb78680bdb50036e97edb034c8b68a9737f" integrity sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ== +itty-time@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/itty-time/-/itty-time-1.0.6.tgz#a6eeda619f19d2f4c480ceddd013b93acb05714d" + integrity sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw== + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -5804,10 +5814,10 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -miniflare@3.20240925.0: - version "3.20240925.0" - resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240925.0.tgz#a291998dedf90bfb4bcfdad033ba030851ff9171" - integrity sha512-2LmQbKHf0n6ertUKhT+Iltixi53giqDH7P71+wCir3OnGyXIODqYwOECx1mSDNhYThpxM2dav8UdPn6SQiMoXw== +miniflare@3.20241022.0: + version "3.20241022.0" + resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20241022.0.tgz#31b8a2bc53b411ac814b55db9c31aebfe475f344" + integrity sha512-x9Fbq1Hmz1f0osIT9Qmj78iX4UpCP2EqlZnA/tzj/3+I49vc3Kq0fNqSSKplcdf6HlCHdL3fOBicmreQF4BUUQ== dependencies: "@cspotcode/source-map-support" "0.8.1" acorn "^8.8.0" @@ -5817,7 +5827,7 @@ miniflare@3.20240925.0: glob-to-regexp "^0.4.1" stoppable "^1.1.0" undici "^5.28.4" - workerd "1.20240925.0" + workerd "1.20241022.0" ws "^8.17.1" youch "^3.2.2" zod "^3.22.3" @@ -7458,10 +7468,10 @@ undici@^5.25.4, undici@^5.28.4: dependencies: "@fastify/busboy" "^2.0.0" -"unenv@npm:unenv-nightly@2.0.0-20240919-125358-9a64854": - version "2.0.0-20240919-125358-9a64854" - resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20240919-125358-9a64854.tgz#13f6812c7b12b9521ea05c6d49259d136e093acd" - integrity sha512-XjsgUTrTHR7iw+k/SRTNjh6EQgwpC9voygnoCJo5kh4hKqsSDHUW84MhL9EsHTNfLctvVBHaSw8e2k3R2fKXsQ== +"unenv@npm:unenv-nightly@2.0.0-20241018-011344-e666fcf": + version "2.0.0-20241018-011344-e666fcf" + resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20241018-011344-e666fcf.tgz#75b6d1ab37e6b5edeec80fe8f403e3de8e9bc50e" + integrity sha512-D00bYn8rzkCBOlLx+k1iHQlc69jvtJRT7Eek4yIGQ6461a2tUBjngGZdRpqsoXAJCz/qBW0NgPting7Zvg+ysg== dependencies: defu "^6.1.4" ohash "^1.1.4" @@ -7672,38 +7682,40 @@ which@^4.0.0: dependencies: isexe "^3.1.1" -workerd@1.20240925.0: - version "1.20240925.0" - resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240925.0.tgz#0a2602eabfa7e1d01d89ff2b600ed359be9b515d" - integrity sha512-/Jj6+yLwfieZGEt3Kx4+5MoufuC3g/8iFaIh4MPBNGJOGYmdSKXvgCqz09m2+tVCYnysRfbq2zcbVxJRBfOCqQ== +workerd@1.20241022.0: + version "1.20241022.0" + resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20241022.0.tgz#45ab10642009b4573ae78df784e0a8c5b338914e" + integrity sha512-jyGXsgO9DRcJyx6Ovv7gUyDPc3UYC2i/E0p9GFUg6GUzpldw4Y93y9kOmdfsOnKZ3+lY53veSiUniiBPE6Q2NQ== optionalDependencies: - "@cloudflare/workerd-darwin-64" "1.20240925.0" - "@cloudflare/workerd-darwin-arm64" "1.20240925.0" - "@cloudflare/workerd-linux-64" "1.20240925.0" - "@cloudflare/workerd-linux-arm64" "1.20240925.0" - "@cloudflare/workerd-windows-64" "1.20240925.0" + "@cloudflare/workerd-darwin-64" "1.20241022.0" + "@cloudflare/workerd-darwin-arm64" "1.20241022.0" + "@cloudflare/workerd-linux-64" "1.20241022.0" + "@cloudflare/workerd-linux-arm64" "1.20241022.0" + "@cloudflare/workerd-windows-64" "1.20241022.0" -wrangler@3.79.0: - version "3.79.0" - resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.79.0.tgz#c23b08ba06bff752b650a567a7fcbe03e4036914" - integrity sha512-29wzQWc5qNKtD3bSyAEX11j/U5IIk8xy2/ZJ4wljJlS5ppff8qGqI+LtlLmqjqTSeQqFLb87xRkms0YFUgNLXg== +wrangler@^3.83.0: + version "3.83.0" + resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.83.0.tgz#bebe3d0067f3430cf6f0b2e8e4ab648c208e002b" + integrity sha512-qDzdUuTngKqmm2OJUZm7Gk4+Hv37F2nNNAHuhIgItEIhxBdOVDsgKmvpd+f41MFxyuGg3fbGWYANHI+0V2Z5yw== dependencies: "@cloudflare/kv-asset-handler" "0.3.4" - "@cloudflare/workers-shared" "0.5.4" + "@cloudflare/workers-shared" "0.7.0" "@esbuild-plugins/node-globals-polyfill" "^0.2.3" "@esbuild-plugins/node-modules-polyfill" "^0.2.2" blake3-wasm "^2.1.5" chokidar "^3.5.3" + date-fns "^4.1.0" esbuild "0.17.19" - miniflare "3.20240925.0" + itty-time "^1.0.6" + miniflare "3.20241022.0" nanoid "^3.3.3" path-to-regexp "^6.3.0" resolve "^1.22.8" resolve.exports "^2.0.2" selfsigned "^2.0.1" source-map "^0.6.1" - unenv "npm:unenv-nightly@2.0.0-20240919-125358-9a64854" - workerd "1.20240925.0" + unenv "npm:unenv-nightly@2.0.0-20241018-011344-e666fcf" + workerd "1.20241022.0" xxhash-wasm "^1.0.1" optionalDependencies: fsevents "~2.3.2" From 1ed98da7fc89c8624a26baf5b0a35e50548f4527 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 01:10:48 +0900 Subject: [PATCH 20/22] refactor: replace UBIQUIBOT_PUBLIC_KEY with KERNEL_PUBLIC_KEY Updated environment variable references and tests for consistency. --- .dev.vars.example | 3 ++- .env.example | 3 ++- .github/workflows/worker-deploy.yml | 2 ++ src/types/env.ts | 1 - tests/__mocks__/handlers.ts | 1 + tests/main.test.ts | 12 +++++++----- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.dev.vars.example b/.dev.vars.example index e602c48..cda5c21 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -1,2 +1,3 @@ SUPABASE_URL= -SUPABASE_KEY= \ No newline at end of file +SUPABASE_KEY= +KERNEL_PUBLIC_KEY= diff --git a/.env.example b/.env.example index e602c48..cda5c21 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ SUPABASE_URL= -SUPABASE_KEY= \ No newline at end of file +SUPABASE_KEY= +KERNEL_PUBLIC_KEY= diff --git a/.github/workflows/worker-deploy.yml b/.github/workflows/worker-deploy.yml index 88c690e..3eced74 100644 --- a/.github/workflows/worker-deploy.yml +++ b/.github/workflows/worker-deploy.yml @@ -41,9 +41,11 @@ jobs: secrets: | SUPABASE_URL SUPABASE_KEY + KERNEL_PUBLIC_KEY env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + KERNEL_PUBLIC_KEY: ${{ secrets.KERNEL_PUBLIC_KEY }} - name: Write Deployment URL to Summary run: | diff --git a/src/types/env.ts b/src/types/env.ts index e5383cc..f0a09c7 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -4,7 +4,6 @@ import { LOG_LEVEL } from "@ubiquity-os/ubiquity-os-logger"; export const envSchema = T.Object({ SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), - UBIQUIBOT_PUBLIC_KEY: T.String(), LOG_LEVEL: T.Optional(T.Enum(LOG_LEVEL)), KERNEL_PUBLIC_KEY: T.Optional(T.String()), }); diff --git a/tests/__mocks__/handlers.ts b/tests/__mocks__/handlers.ts index 3ac2e6e..2905cfe 100644 --- a/tests/__mocks__/handlers.ts +++ b/tests/__mocks__/handlers.ts @@ -194,6 +194,7 @@ export const handlers = [ }); return HttpResponse.json(labels); }), + http.post("http://localhost:65432/rest/v1/access", () => HttpResponse.json()), ]; async function getLabel(body: ReadableStream | null) { diff --git a/tests/main.test.ts b/tests/main.test.ts index 91e45d6..fd1879f 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -157,8 +157,9 @@ describe("User tests", () => { url, } as unknown as Request, { - SUPABASE_URL: "url", + SUPABASE_URL: "http://localhost:65432", SUPABASE_KEY: "key", + KERNEL_PUBLIC_KEY: publicKey, } ); expect(result.ok).toEqual(true); @@ -173,6 +174,7 @@ describe("User tests", () => { { SUPABASE_URL: "url", SUPABASE_KEY: "key", + KERNEL_PUBLIC_KEY: "key", } ); expect(result.ok).toEqual(false); @@ -198,12 +200,12 @@ describe("User tests", () => { }), } as unknown as Request, { - SUPABASE_URL: "url", - SUPABASE_KEY: "key", + SUPABASE_URL: "http://localhost:65432", + KERNEL_PUBLIC_KEY: publicKey, } as unknown as Env ); expect(result.ok).toEqual(false); - expect(result.status).toEqual(400); - expect(errorSpy).toHaveBeenCalled(); + expect(result.status).toEqual(500); + expect(await result.text()).toEqual("Internal Server Error"); }); }); From 3059dc06b068f3b4d9407ee4393364866a9ed810 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 02:24:36 +0900 Subject: [PATCH 21/22] refactor: replace Context with ContextPlugin Updated various files to replace the Context type with ContextPlugin. --- src/handlers/check-modified-base-rate.ts | 4 ++-- src/handlers/get-base-rate-changes.ts | 7 +++---- src/handlers/global-config-update.ts | 20 ++++++++++---------- src/handlers/sync-labels-to-config.ts | 2 +- src/shared/permissions.ts | 4 ++-- src/types/typeguards.ts | 2 +- tests/global-update.test.ts | 4 +++- tests/main.test.ts | 7 +++---- yarn.lock | 24 ++++++++++++------------ 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/handlers/check-modified-base-rate.ts b/src/handlers/check-modified-base-rate.ts index fcbdeba..ab77de1 100644 --- a/src/handlers/check-modified-base-rate.ts +++ b/src/handlers/check-modified-base-rate.ts @@ -1,12 +1,12 @@ import { CONFIG_FULL_PATH, DEV_CONFIG_FULL_PATH } from "@ubiquity-os/ubiquity-os-kernel"; -import { Context } from "../types/context"; +import { ContextPlugin } from "../types/plugin-input"; import { isPushEvent } from "../types/typeguards"; import { getCommitChanges } from "./get-commit-changes"; export const ZERO_SHA = "0000000000000000000000000000000000000000"; const BASE_RATE_FILES = [DEV_CONFIG_FULL_PATH, CONFIG_FULL_PATH]; -export async function isConfigModified(context: Context): Promise { +export async function isConfigModified(context: ContextPlugin): Promise { if (!isPushEvent(context)) { context.logger.debug("Not a push event"); return false; diff --git a/src/handlers/get-base-rate-changes.ts b/src/handlers/get-base-rate-changes.ts index 80392fd..689524d 100644 --- a/src/handlers/get-base-rate-changes.ts +++ b/src/handlers/get-base-rate-changes.ts @@ -1,5 +1,4 @@ -import { Context } from "../types/context"; -import { Rates } from "../types/plugin-input"; +import { ContextPlugin, Rates } from "../types/plugin-input"; import { isPushEvent } from "../types/typeguards"; /** @@ -7,7 +6,7 @@ import { isPushEvent } from "../types/typeguards"; * * This will capture changes to either the plugin's config or the global basePriceMultiplier. */ -export async function getBaseRateChanges(context: Context): Promise { +export async function getBaseRateChanges(context: ContextPlugin): Promise { if (!isPushEvent(context)) { context.logger.debug("Not a push event"); return { @@ -32,7 +31,7 @@ export async function getBaseRateChanges(context: Context): Promise { } try { - commitData = await context.octokit.repos.getCommit({ + commitData = await context.octokit.rest.repos.getCommit({ owner, repo: repository.name, ref: commitSha, diff --git a/src/handlers/global-config-update.ts b/src/handlers/global-config-update.ts index 85fc0bf..4c631b4 100644 --- a/src/handlers/global-config-update.ts +++ b/src/handlers/global-config-update.ts @@ -1,13 +1,13 @@ +import { isUserAdminOrBillingManager, listOrgRepos, listRepoIssues } from "../shared/issue"; +import { Label } from "../types/github"; +import { ContextPlugin } from "../types/plugin-input"; +import { isPushEvent } from "../types/typeguards"; import { isConfigModified } from "./check-modified-base-rate"; import { getBaseRateChanges } from "./get-base-rate-changes"; -import { Context } from "../types/context"; -import { syncPriceLabelsToConfig } from "./sync-labels-to-config"; import { setPriceLabel } from "./pricing-label"; -import { isPushEvent } from "../types/typeguards"; -import { isUserAdminOrBillingManager, listOrgRepos, listRepoIssues } from "../shared/issue"; -import { Label } from "../types/github"; +import { syncPriceLabelsToConfig } from "./sync-labels-to-config"; -async function isAuthed(context: Context): Promise { +async function isAuthed(context: ContextPlugin): Promise { if (!isPushEvent(context)) { context.logger.debug("Not a push event"); return false; @@ -33,7 +33,7 @@ async function isAuthed(context: Context): Promise { return !!(isPusherAuthed && isSenderAuthed); } -export async function globalLabelUpdate(context: Context) { +export async function globalLabelUpdate(context: ContextPlugin) { if (!isPushEvent(context)) { context.logger.debug("Not a push event"); return; @@ -68,7 +68,7 @@ export async function globalLabelUpdate(context: Context) { payload: { repository: repo, }, - } as Context; + } as ContextPlugin; // this should create labels on the repos that are missing await syncPriceLabelsToConfig(ctx); @@ -80,7 +80,7 @@ export async function globalLabelUpdate(context: Context) { } } -async function updateAllIssuePriceLabels(context: Context) { +async function updateAllIssuePriceLabels(context: ContextPlugin) { const { logger, config } = context; const repos = await listOrgRepos(context); @@ -97,7 +97,7 @@ async function updateAllIssuePriceLabels(context: Context) { repository: repo, issue, }, - } as Context, + } as ContextPlugin, issue.labels as Label[], config ); diff --git a/src/handlers/sync-labels-to-config.ts b/src/handlers/sync-labels-to-config.ts index 2684a70..9320c69 100644 --- a/src/handlers/sync-labels-to-config.ts +++ b/src/handlers/sync-labels-to-config.ts @@ -63,7 +63,7 @@ export async function syncPriceLabelsToConfig(context: ContextPlugin): Promise label.name) }); const owner = context.payload.repository.owner?.login; if (!owner) { diff --git a/src/shared/permissions.ts b/src/shared/permissions.ts index e9ba65d..86c8bfa 100644 --- a/src/shared/permissions.ts +++ b/src/shared/permissions.ts @@ -57,10 +57,10 @@ export async function labelAccessPermissionsCheck(context: ContextPlugin) { } async function handleInsufficientPrivileges( - context: Context, + context: ContextPlugin, labelType: string, sender: string, - repo: Context["payload"]["repository"], + repo: ContextPlugin["payload"]["repository"], action: string, labelName: string, eventName: string diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index ce273dc..2e61434 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -16,7 +16,7 @@ export function isIssueLabelEvent(context: ContextPlugin): context is ContextPlu return context.eventName === "issues.labeled" || context.eventName === "issues.unlabeled"; } -export function isPushEvent(context: Context): context is Context & { payload: Context<"push">["payload"] } { +export function isPushEvent(context: ContextPlugin): context is ContextPlugin & { payload: Context<"push">["payload"] } { return context.eventName === "push"; } diff --git a/tests/global-update.test.ts b/tests/global-update.test.ts index fa7d222..ee4cd42 100644 --- a/tests/global-update.test.ts +++ b/tests/global-update.test.ts @@ -1,5 +1,6 @@ import { drop } from "@mswjs/data"; import { Context } from "../src/types/context"; +import { ContextPlugin } from "../src/types/plugin-input"; import { db } from "./__mocks__/db"; import { server } from "./__mocks__/node"; import { it, describe, beforeAll, beforeEach, afterAll, expect, afterEach, jest } from "@jest/globals"; @@ -553,7 +554,7 @@ function createContext( globalConfigUpdate?: { excludeRepos: string[]; } -): Context { +): ContextPlugin { return { adapters: {} as never, payload: { @@ -614,6 +615,7 @@ function createContext( }, basePriceMultiplier: 2, }, + // @ts-expect-error ESM makes types incompatible. octokit: octokit, eventName: "push", env: { diff --git a/tests/main.test.ts b/tests/main.test.ts index fd1879f..cc3d3fe 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -1,6 +1,5 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { drop } from "@mswjs/data"; -import * as crypto from "crypto"; import commandParser, { CommandArguments } from "../src/handlers/command-parser"; import { Env } from "../src/types/env"; import { ContextPlugin } from "../src/types/plugin-input"; @@ -9,12 +8,12 @@ import { db } from "./__mocks__/db"; import { server } from "./__mocks__/node"; import issueCommented from "./__mocks__/requests/issue-comment-post.json"; import usersGet from "./__mocks__/users-get.json"; -import * as crypto from "crypto"; +import * as crypto from "node:crypto"; import { AssistivePricingSettings, pluginSettingsSchema } from "../src/types/plugin-input"; import { Value } from "@sinclair/typebox/value"; import { calculateLabelValue, calculateTaskPrice } from "../src/shared/pricing"; -const { privateKey } = crypto.generateKeyPairSync("rsa", { +const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048, publicKeyEncoding: { type: "spki", @@ -193,7 +192,7 @@ describe("User tests", () => { headers: { get: () => "application/json", }, - url: undefined, + url, json: () => ({ ...data, signature, diff --git a/yarn.lock b/yarn.lock index 19c1472..7e27ce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2158,10 +2158,10 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sinclair/typebox@^0.32.15": - version "0.32.29" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.29.tgz#35a31aac1078f14b722bd08086cea44fa73b206a" - integrity sha512-GWKskKPGQV0vVYizqCu0E1YLwGthvlkDqpRxB3iBuqxJ8dN/9n1cnDRSQHF59GMoxDJwzSgmxpU617SidtUnMw== +"@sinclair/typebox@^0.33.17": + version "0.33.17" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.33.17.tgz#603475bb1fb343deb82a4ce85e6adf177a65739b" + integrity sha512-75232GRx3wp3P7NP+yc4nRK3XUAnaQShxTAzapgmQrgs0QvSq0/mOJGoZXRpH15cFCKyys+4laCPbBselqJ5Ag== "@sinonjs/commons@^3.0.0": version "3.0.1" @@ -2533,10 +2533,10 @@ "@typescript-eslint/types" "7.0.1" eslint-visitor-keys "^3.4.1" -"@ubiquity-os/ubiquity-os-kernel@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@ubiquity-os/ubiquity-os-kernel/-/ubiquity-os-kernel-2.4.0.tgz#1bb74d4b02ef5ba6b0c1c01d509e3e0f58609904" - integrity sha512-KT8AwtMOHA99GoVUs43eAR2PZii9AHmY9NjOlBtvotB5tXbeEIyhjgHr0kgRncgiLJU1UFIe0QYMmpOvmXiQpg== +"@ubiquity-os/ubiquity-os-kernel@^2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@ubiquity-os/ubiquity-os-kernel/-/ubiquity-os-kernel-2.5.1.tgz#13cc77146837deeb7a6e6346511a686be78a832b" + integrity sha512-G+gL/NmZTP7QiijB1CcHXBj78iKW7RYdRC80ETWxzojIR3fZYPxTSb3rWEJOim9iAfQ7qGawJQJGL1yrPuMRBQ== dependencies: "@actions/core" "1.10.1" "@actions/github" "6.0.0" @@ -4520,10 +4520,10 @@ hono@4.4.13: resolved "https://registry.yarnpkg.com/hono/-/hono-4.4.13.tgz#954e8f6e4bab14f3f9d7bac4eef4c56d23e7f900" integrity sha512-c6qqenclmQ6wpXzqiElMa2jt423PVCmgBreDfC5s2lPPpGk7d0lOymd8QTzFZyYC5mSSs6imiTMPip+gLwuW/g== -hono@^4.6.5: - version "4.6.5" - resolved "https://registry.yarnpkg.com/hono/-/hono-4.6.5.tgz#9d5a1ada5b40dc865e2d28c0bcc5d24cc755b9f1" - integrity sha512-qsmN3V5fgtwdKARGLgwwHvcdLKursMd+YOt69eGpl1dUCJb8mCd7hZfyZnBYjxCegBG7qkJRQRUy2oO25yHcyQ== +hono@^4.6.7: + version "4.6.7" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.6.7.tgz#5389be797be4e049991d29ad7aea499e70d28085" + integrity sha512-wX4ZbOnzfNO61hUjuQbJ7OPGs1fWXXVVJ8VTPDb2Ls/x9HjCbVTm80Je6VTHMz5n5RGDtBgV9d9ZFZxBqx56ng== hosted-git-info@^2.1.4: version "2.8.9" From 143d0f5747f1301868339fe3d17bc677ebfa1aa5 Mon Sep 17 00:00:00 2001 From: gentlementlegen Date: Tue, 29 Oct 2024 02:29:06 +0900 Subject: [PATCH 22/22] chore: remove return-data-to-kernel handler Deleted unused handler and cleaned up cspell settings. --- .cspell.json | 5 +++-- src/handlers/return-data-to-kernel.ts | 15 --------------- 2 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 src/handlers/return-data-to-kernel.ts diff --git a/.cspell.json b/.cspell.json index eb6fe0d..b24526b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -28,8 +28,9 @@ "typebox", "typeguards", "mswjs", - "ubiquity-os" - , "hono"], + "ubiquity-os", + "hono" + ], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/src/handlers/return-data-to-kernel.ts b/src/handlers/return-data-to-kernel.ts deleted file mode 100644 index e2bc6d7..0000000 --- a/src/handlers/return-data-to-kernel.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as github from "@actions/github"; -import { Octokit } from "@octokit/rest"; - -export async function returnDataToKernel(repoToken: string, stateId: string, output: object, eventType = "return-data-to-ubiquity-os-kernel") { - const octokit = new Octokit({ auth: repoToken }); - return octokit.repos.createDispatchEvent({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - event_type: eventType, - client_payload: { - state_id: stateId, - output: JSON.stringify(output), - }, - }); -}