├── .github ├── FUNDING.yml └── workflows │ ├── deploy.yml │ └── publish.yml ├── .gitignore ├── .dockerignore ├── .prettierrc ├── Dockerfile ├── wrangler.toml ├── tsconfig.json ├── eslint.config.mjs ├── docker-compose.yml ├── test └── test.sh ├── package.json ├── src ├── util.ts ├── types.ts ├── env.ts ├── md-truncate.ts └── index.ts ├── README.md ├── LICENSE └── bun.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: JRoy 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | .storage 4 | .wrangler 5 | *.capnp 6 | 7 | test/headers.http 8 | test/body.json 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | Dockerfile* 3 | docker-compose* 4 | .dockerignore 5 | .git 6 | .gitignore 7 | .github 8 | .wrangler 9 | README.md 10 | LICENSE 11 | .vscode 12 | Makefile 13 | helm-charts 14 | .env 15 | .editorconfig 16 | .idea 17 | coverage* 18 | test/ 19 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "jsxSingleQuote": true, 7 | "bracketSpacing": true, 8 | "bracketSameLine": false, 9 | "arrowParens": "avoid", 10 | "experimentalTernaries": true, 11 | "plugins": ["prettier-plugin-organize-imports"] 12 | } 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM oven/bun:canary-debian AS builder 2 | 3 | WORKDIR /app 4 | 5 | COPY . . 6 | 7 | RUN bun install --frozen-lockfile 8 | 9 | RUN bun run docker:build 10 | 11 | FROM jacoblincool/workerd:latest 12 | 13 | COPY --from=builder /app/worker.capnp ./worker.capnp 14 | 15 | EXPOSE 8080/tcp 16 | CMD ["serve", "--experimental", "--binary", "worker.capnp"] 17 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "disgit" 2 | main = "src/index.ts" 3 | compatibility_date = "2025-01-01" 4 | 5 | workers_dev = true 6 | 7 | [vars] 8 | IGNORED_BRANCH_REGEX="" 9 | IGNORED_BRANCHES="" 10 | IGNORED_USERS="" 11 | IGNORED_PAYLOADS="" 12 | DEBUG_PASTE=false 13 | EXECUTE_MERGE_QUEUE_BRANCHES=false 14 | 15 | # Uses secrets: 16 | # - GITHUB_WEBHOOK_SECRET 17 | # Run `echo | wrangler secret put ` for each of these 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "lib": ["esnext"], 6 | "jsx": "react", 7 | "types": ["@cloudflare/workers-types"], 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "allowJs": true, 11 | "checkJs": false, 12 | "noEmit": true, 13 | "esModuleInterop": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "strict": true, 16 | "skipLibCheck": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Worker 2 | on: 3 | push: 4 | repository_dispatch: 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 60 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: oven-sh/setup-bun@v2 12 | - name: Build & Deploy Worker 13 | uses: cloudflare/wrangler-action@v3 14 | with: 15 | apiToken: ${{ secrets.CF_API_TOKEN }} 16 | accountId: ${{ secrets.CF_ACCOUNT_ID }} 17 | packageManager: bun 18 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { FlatCompat } from '@eslint/eslintrc'; 2 | import js from '@eslint/js'; 3 | import { defineConfig } from 'eslint/config'; 4 | import path from 'node:path'; 5 | import { fileURLToPath } from 'node:url'; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | const compat = new FlatCompat({ 10 | baseDirectory: __dirname, 11 | recommendedConfig: js.configs.recommended, 12 | allConfig: js.configs.all, 13 | }); 14 | 15 | export default defineConfig([ 16 | { 17 | extends: compat.extends('plugin:prettier/recommended'), 18 | }, 19 | ]); 20 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | worker: 3 | build: . 4 | image: worker 5 | environment: 6 | - IGNORED_BRANCH_REGEX=${IGNORED_BRANCH_REGEX} 7 | - IGNORED_BRANCHES=${IGNORED_BRANCHES} 8 | - IGNORED_USERS=${IGNORED_USERS} 9 | - IGNORED_PAYLOADS=${IGNORED_PAYLOADS} 10 | - DEBUG_PASTE=${DEBUG_PASTE} 11 | volumes: 12 | - ./.storage/cache:/worker/cache 13 | ports: 14 | - "8080:8080" 15 | healthcheck: 16 | test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"] 17 | interval: 15s 18 | timeout: 10s 19 | retries: 3 20 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ $# -ne 2 ]]; then 6 | echo "Usage: $0 " 7 | exit 1 8 | fi 9 | 10 | echo "Running test with ID: $1 and Secret: $2" 11 | 12 | # Script directory, so it works no matter where you call it from 13 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 14 | 15 | HEADERS_FILE="$SCRIPT_DIR/headers.http" 16 | BODY_FILE="$SCRIPT_DIR/body.json" 17 | BASE_URL="http://localhost:8787" 18 | 19 | # Basic sanity‑checks 20 | [[ -f "$HEADERS_FILE" ]] || { echo "Missing $HEADERS_FILE"; exit 1; } 21 | [[ -f "$BODY_FILE" ]] || { echo "Missing $BODY_FILE"; exit 1; } 22 | 23 | curl -vv --show-error --fail \ 24 | -X POST \ 25 | -H @"$HEADERS_FILE" \ 26 | --data @"$BODY_FILE" \ 27 | "${BASE_URL}/$1/$2" 28 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | name: Publish 11 | steps: 12 | - name: Checkout Repository 13 | uses: actions/checkout@v4 14 | - name: Login to GitHub Container Registry 15 | uses: docker/login-action@v3 16 | with: 17 | registry: ghcr.io 18 | username: ${{ github.actor }} 19 | password: ${{ secrets.GITHUB_TOKEN }} 20 | - name: Generate tag 21 | id: tag 22 | run: | 23 | ts=$(date +%s) 24 | branch=${GITHUB_REF##*/} 25 | echo "IMAGE_ID=${branch}-${GITHUB_SHA::8}-${ts}" >> "$GITHUB_OUTPUT" 26 | - name: Publish Docker image 27 | uses: docker/build-push-action@v6 28 | with: 29 | context: . 30 | push: true 31 | tags: | 32 | ghcr.io/jroy/disgit:latest 33 | ghcr.io/jroy/disgit:${{ steps.tag.outputs.IMAGE_ID }} 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "disgit", 3 | "version": "1.0.0", 4 | "description": "A Cloudflare Worker which provides better GitHub->Discord webhook integration than the built-in Discord webhook executor.", 5 | "license": "Apache-2.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/JRoy/disgit.git" 9 | }, 10 | "private": true, 11 | "dependencies": { 12 | "@cloudflare/workers-types": "^4.20250607.0", 13 | "@octokit/openapi-webhooks-types": "^12.0.3", 14 | "typescript": "^5.8.3", 15 | "wrangler": "^4.19.1" 16 | }, 17 | "devDependencies": { 18 | "@eslint/eslintrc": "^3.3.1", 19 | "@eslint/js": "^9.30.1", 20 | "selflare": "^1.1.2", 21 | "eslint": "^9.28.0", 22 | "eslint-config-prettier": "^10.1.5", 23 | "eslint-plugin-prettier": "^5.4.1", 24 | "prettier": "^3.6.2", 25 | "prettier-plugin-organize-imports": "^4.1.0" 26 | }, 27 | "scripts": { 28 | "docker:build": "WRANGLER_SEND_METRICS=false wrangler deploy --dry-run --outdir .wrangler/dist && selflare compile --script .wrangler/dist/index.js", 29 | "build": "selflare compile", 30 | "start": "wrangler dev src/index.ts --local=true", 31 | "docker": "wrangler dev index.ts --local=true", 32 | "deploy": "wranger deploy", 33 | "check": "tsc" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import {mdTruncate} from "./md-truncate"; 2 | 3 | function convertDetailsToSpoilers(text: string, hideDetailsSummary: boolean): string { 4 | const detailsRegex = /]*>\s*]*>(.*?)<\/summary>\s*(.*?)<\/details>/gis; 5 | 6 | return text.replace(detailsRegex, (_, summary: string, content: string) => { 7 | const cleanSummary = summary.trim().replace(/<[^>]*>/g, ''); 8 | 9 | // Remove HTML tags but preserve Markdown formatting 10 | const cleanContent = content.trim() 11 | .replace(/<[^>]*>/g, '') 12 | // Normalize whitespace but preserve line breaks for code blocks 13 | .replace(/\n\s*\n/g, '\n') 14 | // Remove excessive whitespace but keep single spaces 15 | .replace(/[ \t]+/g, ' ') 16 | .trim(); 17 | if (cleanContent && !hideDetailsSummary) { 18 | return `**${cleanSummary}**:\n ||${cleanContent}||`; 19 | } else { 20 | return `**${cleanSummary}**`; 21 | } 22 | }); 23 | } 24 | 25 | export function truncate(str: string, num: number, hideDetailsBody: boolean): string | null { 26 | if (str === null) { 27 | return null; 28 | } 29 | 30 | // Remove HTML comments 31 | str = str.replace(/[\n|\r]*/g, ""); 32 | 33 | // Convert details/summary to Discord spoilers 34 | str = convertDetailsToSpoilers(str, hideDetailsBody); 35 | 36 | if (str.length <= num) { 37 | return str; 38 | } 39 | 40 | let truncatedStr = mdTruncate(str, {limit: num, ellipsis: true}); 41 | 42 | // mdTruncate doesn't count formatting markers, so we need to ensure the length is correct 43 | let trimNum = num; 44 | while (truncatedStr.length < num) { 45 | trimNum -= 10; 46 | truncatedStr = mdTruncate(str, {limit: num, ellipsis: true}); 47 | } 48 | 49 | return truncatedStr; 50 | } 51 | 52 | export function shortCommit(hash: string): string { 53 | return hash.substring(0, 7); 54 | } 55 | 56 | export async function validateRequest(request: Request, secret: string): Promise { 57 | const signatureHeader = request.headers.get("X-Hub-Signature-256")?.substring("sha256=".length); 58 | if (signatureHeader == null) { 59 | return false; 60 | } 61 | 62 | const encoder = new TextEncoder(); 63 | const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { 64 | name: "HMAC", 65 | hash: "SHA-256" 66 | }, false, ["verify"]); 67 | 68 | 69 | return crypto.subtle.verify("HMAC", key, encoder.encode(signatureHeader), await request.arrayBuffer()) 70 | } 71 | 72 | export type Sender = { 73 | login: string; 74 | html_url: string; 75 | avatar_url: string; 76 | } 77 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import {components} from "@octokit/openapi-webhooks-types"; 2 | 3 | export type PingWebhookPayload = components['schemas']['webhook-ping']; 4 | export type ReleaseCreatedWebhookPayload = components['schemas']['webhook-release-created']; 5 | export type PrereleaseCreatedWebhookPayload = components['schemas']['webhook-release-prereleased']; 6 | export type PushWebhookPayload = components['schemas']['webhook-push']; 7 | export type PullRequestEnqueuedWebhookPayload = components['schemas']['webhook-pull-request-enqueued']; 8 | export type PullRequestDequeuedWebhookPayload = components['schemas']['webhook-pull-request-dequeued']; 9 | export type PullRequestReviewCommentWebhookPayload = components['schemas']['webhook-pull-request-review-comment-created']; 10 | export type PullRequestReviewSubmittedWebhookPayload = components['schemas']['webhook-pull-request-review-submitted']; 11 | export type PullRequestReviewDismissedWebhookPayload = components['schemas']['webhook-pull-request-review-dismissed']; 12 | export type PullRequestReadyWebhookPayload = components['schemas']['webhook-pull-request-ready-for-review']; 13 | export type PullRequestDraftWebhookPayload = components['schemas']['webhook-pull-request-converted-to-draft']; 14 | export type PullRequestReopenedWebhookPayload = components['schemas']['webhook-pull-request-reopened']; 15 | export type PullRequestClosedWebhookPayload = components['schemas']['webhook-pull-request-closed']; 16 | export type PullRequestOpenedWebhookPayload = components['schemas']['webhook-pull-request-opened']; 17 | export type IssueCommentCreatedWebhookPayload = components['schemas']['webhook-issue-comment-created']; 18 | export type IssueCreatedWebhookPayload = components['schemas']['webhook-issues-opened']; 19 | export type IssueClosedWebhookPayload = components['schemas']['webhook-issues-closed']; 20 | export type IssueReopenedWebhookPayload = components['schemas']['webhook-issues-reopened']; 21 | export type PackagePublishedWebhookPayload = components['schemas']['webhook-package-published']; 22 | export type PackageUpdatedWebhookPayload = components['schemas']['webhook-package-updated']; 23 | export type ForkWebhookPayload = components['schemas']['webhook-fork']; 24 | export type DiscussionCommentCreatedWebhookPayload = components['schemas']['webhook-discussion-comment-created']; 25 | export type DiscussionCreatedWebhookPayload = components['schemas']['webhook-discussion-created']; 26 | export type BranchDeletedWebhookPayload = components['schemas']['webhook-delete']; 27 | export type BranchCreatedWebhookPayload = components['schemas']['webhook-create']; 28 | export type CommitCommentCreatedWebhookPayload = components['schemas']['webhook-commit-comment-created']; 29 | export type CheckRunCompletedWebhookPayload = components['schemas']['webhook-check-run-completed']; 30 | export type StarCreatedWebhookPayload = components['schemas']['webhook-star-created']; 31 | export type DeploymentCreatedWebhookPayload = components['schemas']['webhook-deployment-created']; 32 | export type DeploymentStatusCreatedWebhookPayload = components['schemas']['webhook-deployment-status-created']; 33 | export type WikiWebhookPayload = components['schemas']['webhook-gollum']; 34 | -------------------------------------------------------------------------------- /src/env.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Raw environment from Workers 3 | */ 4 | export interface Env { 5 | IGNORED_BRANCHES_REGEX: string; 6 | IGNORED_BRANCHES: string; 7 | IGNORED_USERS: string; 8 | IGNORED_PAYLOADS: string; 9 | 10 | GITHUB_WEBHOOK_SECRET: string; 11 | 12 | DEBUG_PASTE: string; 13 | AWAIT_ERRORS: string; 14 | EXECUTE_MERGE_QUEUE_BRANCHES: string; 15 | HIDE_DETAILS_BODY: string; 16 | } 17 | 18 | /** 19 | * Parsed environment 20 | */ 21 | export class BoundEnv { 22 | private ignoredBranchPattern?: RegExp; 23 | private ignoredBranches: string[]; 24 | private ignoredUsers: string[]; 25 | private ignoredPayloads: string[]; 26 | readonly githubWebhookSecret: string; 27 | readonly debugPaste: boolean; 28 | readonly awaitErrors: boolean; 29 | readonly executeMergeQueueBranches: boolean; 30 | readonly hideDetailsBody: boolean; 31 | 32 | constructor(env: Env) { 33 | if (typeof env.IGNORED_BRANCHES_REGEX !== 'undefined') { 34 | this.ignoredBranchPattern = new RegExp(env.IGNORED_BRANCHES_REGEX); 35 | } 36 | this.ignoredBranches = env.IGNORED_BRANCHES?.split(",") || []; 37 | this.ignoredUsers = env.IGNORED_USERS?.split(",") || []; 38 | this.ignoredPayloads = env.IGNORED_PAYLOADS?.split(",") || []; 39 | this.githubWebhookSecret = env.GITHUB_WEBHOOK_SECRET; 40 | this.debugPaste = env.DEBUG_PASTE == "true" || env.DEBUG_PASTE == "1"; 41 | this.awaitErrors = env.AWAIT_ERRORS == "true" || env.AWAIT_ERRORS == "1"; 42 | this.executeMergeQueueBranches = env.EXECUTE_MERGE_QUEUE_BRANCHES == "true" || env.EXECUTE_MERGE_QUEUE_BRANCHES == "1"; 43 | this.hideDetailsBody = env.HIDE_DETAILS_BODY == "true" || env.HIDE_DETAILS_BODY == "1"; 44 | } 45 | 46 | /** 47 | * @param {String} branch 48 | * @return {boolean} 49 | */ 50 | isIgnoredBranch(branch: string): boolean { 51 | if (!this.executeMergeQueueBranches && branch.startsWith('gh-readonly-queue/')) { 52 | return true; 53 | } 54 | 55 | return (this.ignoredBranchPattern && branch.match(this.ignoredBranchPattern) != null) || this.ignoredBranches.includes(branch); 56 | } 57 | 58 | /** 59 | * @param {String} user 60 | * @return {boolean} 61 | */ 62 | isIgnoredUser(user: string): boolean { 63 | return this.ignoredUsers.includes(user); 64 | } 65 | 66 | /** 67 | * @param {String} payload 68 | * @return {boolean} 69 | */ 70 | isIgnoredPayload(payload: string): boolean { 71 | return this.ignoredPayloads.includes(payload); 72 | } 73 | 74 | async buildDebugPaste(embed: any): Promise { 75 | embed = JSON.stringify({ 76 | "files": [ 77 | { 78 | "content": { 79 | "format": "text", 80 | "value": embed 81 | } 82 | } 83 | ] 84 | }); 85 | 86 | embed = await (await fetch("https://api.pastes.dev/post", { 87 | headers: { 88 | "user-agent": "disgit", 89 | "content-type": "application/json", 90 | }, 91 | method: "POST", 92 | body: embed 93 | })).text(); 94 | 95 | embed = JSON.stringify({ 96 | "content": embed 97 | }); 98 | return embed; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # disgit 2 | A Cloudflare Worker (or Docker Container) which provides better GitHub->Discord webhook integration than the built-in Discord webhook executor. 3 | 4 | You can use this Cloudflare worker by following the steps after clicking the button below 5 | 6 | [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/JRoy/disgit) 7 | 8 | 9 | You can also deploy disgit to docker container: 10 | * Docker Compose: Clone this repository and run `docker compose up --build -d`. 11 | * The worker will be started on port 8080 12 | * Docker Image: The disgit container image is published to the GitHub Container Registry [here](https://github.com/JRoy/disgit/pkgs/container/disgit). For more information on how to authenticate with GitHub's container registry, check the help article [here](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-to-the-container-registry). 13 | 14 | ## Environment Variables 15 | disgit has the following optional environment variables that you can use to customize your instance; 16 | - `IGNORED_BRANCHES_REGEX` - A regex pattern for branches that should be ignored 17 | - `IGNORED_BRANCHES` - A comma seperated list of branches that should be ignored 18 | - `IGNORED_USERS` - A comma seperated list of users that should be ignored 19 | - `IGNORED_PAYLOADS` - A comma seperated list of webhook events that should be ignored 20 | - `DEBUG_PASTE` - Set to `true` to enable debug embeds. 21 | - `EXECUTE_MERGE_QUEUE_BRANCHES` - Set to `true` to unignore merge queue related branches. 22 | - `HIDE_DETAILS_BODY` - Set to `true` to omit the body of details tags from messages. This will cause just summary to be shown in the message. 23 | 24 | ## Supported Events 25 | The following webhook events are supported as of now; 26 | * [check_run](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#check_run) 27 | * [commit_comment](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#commit_comment) 28 | * [create](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#create) 29 | * [delete](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#delete) 30 | * [deployment](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#deployment) 31 | * [deployment_status](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#deployment_status) 32 | * [discussion](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#discussion) 33 | * [discussion_comment](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#discussion_comment) 34 | * [fork](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#fork) 35 | * [gollum](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#gollum) (wiki) 36 | * [issue_comment](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment) 37 | * This event also sends pull request comments...*sigh* 38 | * [issues](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#issues) 39 | * [package](https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#package) 40 | * [ping](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#ping) 41 | * [pull_request](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request) 42 | * [pull_request_review](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review) 43 | * [pull_request_review_comment](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_comment) 44 | * [push](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#push) 45 | * [release](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#release) 46 | * [star](https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#star) 47 | * ...feel free to contribute more that suit your needs! 48 | -------------------------------------------------------------------------------- /src/md-truncate.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * from https://github.com/pchiwan/markdown-truncate 3 | **/ 4 | 5 | export const ASTERISK_ITALIC = '*'; 6 | export const UNDERSCORE_ITALIC = '_'; 7 | export const ASTERISK_BOLD = '**'; 8 | export const UNDERSCORE_BOLD = '__'; 9 | export const BACKTICK = '`'; 10 | export const TRIPLE_BACKTICKS = '```'; 11 | export const ESCAPED_UNDERSCORE = '\\_'; 12 | export const ESCAPED_ASTERISK = '\\*'; 13 | 14 | export const ESCAPED_ASTERISK_REGEXP = /\\\*/g; 15 | export const ASTERISK_PLACEHOLDER_REGEXP = /ASTERISKPLACEHOLDER/gm; 16 | 17 | export const ESCAPED_UNDERSCORE_REGEXP = /\\_/g; 18 | export const UNDERSCORE_PLACEHOLDER_REGEXP = /UNDERSCOREPLACEHOLDER/gm; 19 | 20 | export const UNDERSCORE_BOLD_PLACEHOLDER_REGEXP = /UNDERSCOREBOLDPLACEHOLDER/gm; 21 | export const UNDERSCORE_BOLD_REGEXP = /(__)(.*?)(__)/g; 22 | 23 | export const ASTERISK_BOLD_PLACEHOLDER_REGEXP = /ASTERISKBOLDPLACEHOLDER/gm; 24 | export const ASTERISK_BOLD_REGEXP = /(\*\*)(.*?)(\*\*)/g; 25 | 26 | export const UNDERSCORE_ITALIC_PLACEHOLDER_REGEXP = /UNDERSCOREITALICPLACEHOLDER/gm; 27 | export const UNDERSCORE_ITALIC_REGEXP = /(_)(.*?)(_)/g; 28 | 29 | export const ASTERISK_ITALIC_PLACEHOLDER_REGEXP = /ASTERISKITALICPLACEHOLDER/gm; 30 | export const ASTERISK_ITALIC_REGEXP = /(\*)(.*?)(\*)/g; 31 | 32 | export const TRIPLE_BACKTICKS_PLACEHOLDER_REGEXP = /TRIPLEBACKTICKSPLACEHOLDER/gm; 33 | export const TRIPLE_BACKTICKS_REGEXP = /(```)(.*?)(```)/gs; 34 | 35 | export const BACKTICK_PLACEHOLDER_REGEXP = /BACKTICKPLACEHOLDER/gm; 36 | export const BACKTICK_REGEXP = /(`)(.*?)(`)/gs; 37 | 38 | const HYPERLINK = /^\[([^[]+)\]\(([^)]+)\)/; 39 | 40 | const replaceFormatMarkersWithPlaceholders = (text: string) => 41 | text 42 | .replace(ESCAPED_UNDERSCORE_REGEXP, UNDERSCORE_PLACEHOLDER_REGEXP.source) 43 | .replace(ESCAPED_ASTERISK_REGEXP, ASTERISK_PLACEHOLDER_REGEXP.source) 44 | .replace( 45 | UNDERSCORE_BOLD_REGEXP, 46 | `${UNDERSCORE_BOLD_PLACEHOLDER_REGEXP.source}$2${UNDERSCORE_BOLD_PLACEHOLDER_REGEXP.source}` 47 | ) 48 | .replace( 49 | ASTERISK_BOLD_REGEXP, 50 | `${ASTERISK_BOLD_PLACEHOLDER_REGEXP.source}$2${ASTERISK_BOLD_PLACEHOLDER_REGEXP.source}` 51 | ) 52 | .replace( 53 | UNDERSCORE_ITALIC_REGEXP, 54 | `${UNDERSCORE_ITALIC_PLACEHOLDER_REGEXP.source}$2${UNDERSCORE_ITALIC_PLACEHOLDER_REGEXP.source}` 55 | ) 56 | .replace( 57 | ASTERISK_ITALIC_REGEXP, 58 | `${ASTERISK_ITALIC_PLACEHOLDER_REGEXP.source}$2${ASTERISK_ITALIC_PLACEHOLDER_REGEXP.source}` 59 | ) 60 | .replace( 61 | TRIPLE_BACKTICKS_REGEXP, 62 | `${TRIPLE_BACKTICKS_PLACEHOLDER_REGEXP.source}$2${TRIPLE_BACKTICKS_PLACEHOLDER_REGEXP.source}` 63 | ) 64 | .replace( 65 | BACKTICK_REGEXP, 66 | `${BACKTICK_PLACEHOLDER_REGEXP.source}$2${BACKTICK_PLACEHOLDER_REGEXP.source}` 67 | ) 68 | 69 | const replaceFormatPlaceholdersWithMarkers = (text: string) => 70 | text 71 | .replace(UNDERSCORE_PLACEHOLDER_REGEXP, ESCAPED_UNDERSCORE) 72 | .replace(ASTERISK_PLACEHOLDER_REGEXP, ESCAPED_ASTERISK) 73 | .replace(UNDERSCORE_BOLD_PLACEHOLDER_REGEXP, UNDERSCORE_BOLD) 74 | .replace(ASTERISK_BOLD_PLACEHOLDER_REGEXP, ASTERISK_BOLD) 75 | .replace(UNDERSCORE_ITALIC_PLACEHOLDER_REGEXP, UNDERSCORE_ITALIC) 76 | .replace(ASTERISK_ITALIC_PLACEHOLDER_REGEXP, ASTERISK_ITALIC) 77 | .replace(TRIPLE_BACKTICKS_PLACEHOLDER_REGEXP, TRIPLE_BACKTICKS) 78 | .replace(BACKTICK_PLACEHOLDER_REGEXP, BACKTICK); 79 | 80 | const formatMarkers = [ 81 | ASTERISK_BOLD_PLACEHOLDER_REGEXP.source, 82 | UNDERSCORE_BOLD_PLACEHOLDER_REGEXP.source, 83 | ASTERISK_ITALIC_PLACEHOLDER_REGEXP.source, 84 | UNDERSCORE_ITALIC_PLACEHOLDER_REGEXP.source, 85 | BACKTICK_PLACEHOLDER_REGEXP.source, 86 | TRIPLE_BACKTICKS_PLACEHOLDER_REGEXP.source, 87 | ]; 88 | 89 | const formatPlaceholdersMap = { 90 | [UNDERSCORE_PLACEHOLDER_REGEXP.source]: ESCAPED_UNDERSCORE.length, 91 | [ASTERISK_PLACEHOLDER_REGEXP.source]: ESCAPED_ASTERISK.length, 92 | } 93 | 94 | const findFormatPlaceholderAhead = (text: string) => { 95 | const formatPlaceholders = Object.keys(formatPlaceholdersMap); 96 | 97 | for (let i = 0, l = formatPlaceholders.length; i < l; i++) { 98 | if (text.startsWith(formatPlaceholders[i])) { 99 | return formatPlaceholders[i]; 100 | } 101 | } 102 | 103 | return null; 104 | } 105 | 106 | const findFormatMarkerAhead = (text: string, formatStack: any[]) => { 107 | for (let i = 0, l = formatMarkers.length; i < l; i++) { 108 | if (text.startsWith(formatMarkers[i])) { 109 | if (formatStack[formatStack.length - 1] === formatMarkers[i]) { 110 | formatStack.pop(); 111 | } else { 112 | formatStack.push(formatMarkers[i]); 113 | } 114 | return formatMarkers[i]; 115 | } 116 | } 117 | 118 | return null; 119 | }; 120 | 121 | const truncate = (text: string, limit: number, ellipsis: boolean | undefined) => { 122 | let count = 0; 123 | 124 | const truncateString = (text: string) => { 125 | let formatStack: string[] = []; 126 | let skipCountIncrement = false; 127 | let outputText = ''; 128 | let index = 0; 129 | 130 | while (count < limit && index < text.length) { 131 | const formatMarker = findFormatMarkerAhead(text.substring(index), formatStack); 132 | if (formatMarker) { 133 | outputText += formatMarker; 134 | index += formatMarker.length; 135 | skipCountIncrement = true; 136 | } 137 | 138 | const formatPlaceholder = findFormatPlaceholderAhead(text.substring(index)); 139 | if (formatPlaceholder) { 140 | outputText += formatPlaceholder; 141 | index += formatPlaceholder.length; 142 | skipCountIncrement = true; 143 | count += formatPlaceholdersMap[formatPlaceholder]; 144 | } 145 | 146 | const hyperlinkAheadRegexp = new RegExp(HYPERLINK); 147 | const hyperlinkMatch = hyperlinkAheadRegexp.exec(text.substring(index)); 148 | if (hyperlinkMatch) { 149 | const hyperlinkText = hyperlinkMatch[1]; 150 | const hyperlinkUrl = hyperlinkMatch[2]; 151 | 152 | outputText += `[${truncateString(hyperlinkText)}](${hyperlinkUrl})`; 153 | index += hyperlinkMatch[0].length; 154 | skipCountIncrement = true; 155 | } 156 | 157 | if (!formatMarker && !hyperlinkMatch) { 158 | outputText += text[index]; 159 | index++; 160 | } 161 | 162 | if (!skipCountIncrement) { 163 | count++; 164 | } 165 | 166 | skipCountIncrement = false; 167 | } 168 | 169 | outputText = outputText.trimEnd(); 170 | 171 | while (formatStack.length > 0) { 172 | outputText += formatStack.pop(); 173 | } 174 | 175 | return outputText; 176 | }; 177 | 178 | let outputText = truncateString(text); 179 | 180 | if (ellipsis && outputText.length < text.length) { 181 | outputText += '...'; 182 | } 183 | 184 | return outputText; 185 | }; 186 | 187 | export interface MdTruncateOptions { 188 | limit?: number; 189 | ellipsis?: boolean; 190 | } 191 | 192 | export function mdTruncate(text: string = '', options: MdTruncateOptions = {}): string { 193 | const { limit, ellipsis } = options; 194 | 195 | if (isNaN(Number(limit)) || text.length <= (limit ?? 0)) { 196 | return text; 197 | } 198 | 199 | let outputText = replaceFormatMarkersWithPlaceholders(text); 200 | outputText = truncate(outputText, limit ?? 0, ellipsis); 201 | outputText = replaceFormatPlaceholdersWithMarkers(outputText); 202 | return outputText; 203 | } 204 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { BoundEnv, Env } from './env'; 2 | import { 3 | BranchCreatedWebhookPayload, 4 | BranchDeletedWebhookPayload, 5 | CheckRunCompletedWebhookPayload, 6 | CommitCommentCreatedWebhookPayload, 7 | DeploymentCreatedWebhookPayload, 8 | DeploymentStatusCreatedWebhookPayload, 9 | DiscussionCommentCreatedWebhookPayload, 10 | DiscussionCreatedWebhookPayload, 11 | ForkWebhookPayload, 12 | IssueClosedWebhookPayload, 13 | IssueCommentCreatedWebhookPayload, 14 | IssueCreatedWebhookPayload, 15 | IssueReopenedWebhookPayload, 16 | PackagePublishedWebhookPayload, 17 | PackageUpdatedWebhookPayload, 18 | PingWebhookPayload, 19 | PrereleaseCreatedWebhookPayload, 20 | PullRequestClosedWebhookPayload, 21 | PullRequestDequeuedWebhookPayload, 22 | PullRequestDraftWebhookPayload, 23 | PullRequestEnqueuedWebhookPayload, 24 | PullRequestOpenedWebhookPayload, 25 | PullRequestReadyWebhookPayload, 26 | PullRequestReopenedWebhookPayload, 27 | PullRequestReviewCommentWebhookPayload, 28 | PullRequestReviewDismissedWebhookPayload, 29 | PullRequestReviewSubmittedWebhookPayload, 30 | PushWebhookPayload, 31 | ReleaseCreatedWebhookPayload, 32 | StarCreatedWebhookPayload, 33 | WikiWebhookPayload, 34 | } from './types'; 35 | import { Sender, shortCommit, truncate } from './util'; 36 | 37 | async function handleRequest( 38 | request: Request, 39 | env: BoundEnv, 40 | ): Promise { 41 | const event = request.headers.get('X-GitHub-Event'); 42 | const contentType = request.headers.get('content-type'); 43 | if (event != null && contentType != null) { 44 | /*if (!(await validateRequest(request, env.githubWebhookSecret))) { 45 | return new Response('Invalid secret', { status: 403 }); 46 | }*/ 47 | let json: any; 48 | if (contentType.includes('application/json')) { 49 | json = await request.json(); 50 | } else if (contentType.includes('application/x-www-form-urlencoded')) { 51 | json = JSON.parse((await request.formData()).get('payload') as string); 52 | } else { 53 | return new Response(`Unknown content type ${contentType}`, { 54 | status: 400, 55 | }); 56 | } 57 | 58 | let embed = buildEmbed(json, event, env); 59 | if (embed == null) { 60 | return new Response('Webhook NO-OP', { status: 200 }); 61 | } 62 | 63 | if (env.debugPaste) { 64 | embed = await env.buildDebugPaste(embed); 65 | } 66 | 67 | const url = new URL(request.url); 68 | let [hookId, hookToken] = (url.pathname + url.search) 69 | .substring(1) 70 | .split('/'); 71 | 72 | if (typeof hookToken == 'undefined') { 73 | return new Response('Missing Webhook Authorization', { status: 400 }); 74 | } 75 | 76 | const result = await fetch( 77 | `https://discord.com/api/webhooks/${hookId}/${hookToken}`, 78 | { 79 | headers: { 80 | 'content-type': 'application/json;charset=UTF=8', 81 | }, 82 | method: 'POST', 83 | body: embed, 84 | }, 85 | ); 86 | 87 | if (result.ok) { 88 | return new Response(`disgit successfully executed webhook ${hookId}`, { 89 | status: 200, 90 | }); 91 | } 92 | 93 | return new Response( 94 | `Failed to send webhook ${hookId}: Got ${result.status} from discord: ${await result.text()}`, 95 | { status: 400 }, 96 | ); 97 | } else { 98 | return new Response('Bad Request', { status: 400 }); 99 | } 100 | } 101 | 102 | function buildEmbed(json: any, event: string, env: BoundEnv): string | null { 103 | const { action } = json; 104 | 105 | if (env.isIgnoredPayload(event)) { 106 | return null; 107 | } 108 | 109 | switch (event) { 110 | case 'check_run': { 111 | if (action !== 'completed') { 112 | break; 113 | } 114 | return buildCheck(json, env); 115 | } 116 | case 'commit_comment': { 117 | if (action !== 'created') { 118 | break; 119 | } 120 | return buildCommitComment(json, env); 121 | } 122 | case 'create': { 123 | return buildCreateBranch(json, env); 124 | } 125 | case 'delete': { 126 | return buildDeleteBranch(json, env); 127 | } 128 | case 'discussion': { 129 | if (action !== 'created') { 130 | break; 131 | } 132 | return buildDiscussion(json, env); 133 | } 134 | case 'discussion_comment': { 135 | if (action !== 'created') { 136 | break; 137 | } 138 | return buildDiscussionComment(json, env); 139 | } 140 | case 'fork': { 141 | return buildFork(json, env); 142 | } 143 | case 'issue_comment': { 144 | if (action !== 'created') { 145 | break; 146 | } 147 | return buildIssueComment(json, env); 148 | } 149 | case 'issues': { 150 | switch (action) { 151 | case 'opened': { 152 | return buildIssue(json, env); 153 | } 154 | case 'reopened': { 155 | return buildIssueReOpen(json, env); 156 | } 157 | case 'closed': { 158 | return buildIssueClose(json, env); 159 | } 160 | default: { 161 | return null; 162 | } 163 | } 164 | } 165 | case 'package': { 166 | switch (action) { 167 | case 'published': { 168 | return buildPackagePublished(json, env); 169 | } 170 | case 'updated': { 171 | return buildPackageUpdated(json, env); 172 | } 173 | default: { 174 | return null; 175 | } 176 | } 177 | } 178 | case 'ping': { 179 | return buildPing(json, env); 180 | } 181 | case 'pull_request': { 182 | switch (action) { 183 | case 'opened': { 184 | return buildPull(json, env); 185 | } 186 | case 'closed': { 187 | return buildPullClose(json, env); 188 | } 189 | case 'reopened': { 190 | return buildPullReopen(json, env); 191 | } 192 | case 'converted_to_draft': { 193 | return buildPullDraft(json, env); 194 | } 195 | case 'ready_for_review': { 196 | return buildPullReadyReview(json, env); 197 | } 198 | case 'enqueued': { 199 | return buildPullEnqueue(json, env); 200 | } 201 | case 'dequeued': { 202 | return buildPullDequeue(json, env); 203 | } 204 | default: { 205 | return null; 206 | } 207 | } 208 | } 209 | case 'pull_request_review': { 210 | switch (action) { 211 | case 'submitted': 212 | case 'dismissed': { 213 | return buildPullReview(json, env); 214 | } 215 | default: { 216 | return null; 217 | } 218 | } 219 | } 220 | case 'pull_request_review_comment': { 221 | if (action !== 'created') { 222 | break; 223 | } 224 | return buildPullReviewComment(json, env); 225 | } 226 | case 'push': { 227 | return buildPush(json, env); 228 | } 229 | case 'release': { 230 | if (action === 'released' || action === 'prereleased') { 231 | return buildRelease(json, env); 232 | } 233 | break; 234 | } 235 | case 'star': { 236 | if (action !== 'created') { 237 | break; 238 | } 239 | return buildStar(json, env); 240 | } 241 | case 'deployment': { 242 | if (action !== 'created') { 243 | break; 244 | } 245 | return buildDeployment(json, env); 246 | } 247 | case 'deployment_status': { 248 | return buildDeploymentStatus(json, env); 249 | } 250 | // Wiki 251 | case 'gollum': { 252 | return buildWiki(json, env); 253 | } 254 | } 255 | 256 | return null; 257 | } 258 | 259 | function buildEmbedBody( 260 | env: BoundEnv, 261 | title: string, 262 | url: string | undefined, 263 | sender: Sender, 264 | color: number, 265 | description?: string | null, 266 | footer?: string, 267 | fields?: any[], 268 | ): string { 269 | const date = new Date(); 270 | const avatarHash = `${date.getFullYear()}${date.getMonth()}${date.getDay()}`; 271 | return JSON.stringify({ 272 | embeds: [ 273 | { 274 | title: truncate(title, 255, env.hideDetailsBody), 275 | url, 276 | description: 277 | description ? 278 | truncate(description, 1000, env.hideDetailsBody) 279 | : undefined, 280 | author: { 281 | name: truncate(sender.login, 255, env.hideDetailsBody), 282 | url: sender.html_url, 283 | icon_url: `${sender.avatar_url}?=${avatarHash}`, 284 | }, 285 | color, 286 | footer: 287 | footer ? 288 | { 289 | text: truncate(footer, 255, env.hideDetailsBody), 290 | } 291 | : undefined, 292 | fields: fields ?? [], 293 | }, 294 | ], 295 | }); 296 | } 297 | 298 | function buildPing(json: PingWebhookPayload, env: BoundEnv): string | null { 299 | const { zen, hook, repository, sender, organization } = json; 300 | if (!sender) { 301 | return null; 302 | } 303 | 304 | const isOrg = hook?.['type'] === 'Organization'; 305 | 306 | const name = isOrg ? organization?.['login'] : repository?.['full_name']; 307 | 308 | return buildEmbedBody( 309 | env, 310 | `[${name}] ${hook?.type} hook ping received`, 311 | undefined, 312 | sender, 313 | 12118406, 314 | zen, 315 | ); 316 | } 317 | 318 | function buildRelease( 319 | json: ReleaseCreatedWebhookPayload | PrereleaseCreatedWebhookPayload, 320 | env: BoundEnv, 321 | ): string | null { 322 | const { release, repository, sender } = json; 323 | const { draft, name, tag_name, body, html_url, prerelease } = release; 324 | 325 | if (draft || !sender) { 326 | return null; 327 | } 328 | 329 | let effectiveName = name == null ? tag_name : name; 330 | 331 | return buildEmbedBody( 332 | env, 333 | `[${repository['full_name']}] New ${prerelease ? 'pre' : ''}release published: ${effectiveName}`, 334 | html_url, 335 | sender, 336 | 14573028, 337 | body, 338 | ); 339 | } 340 | 341 | function buildPush(json: PushWebhookPayload, env: BoundEnv): string | null { 342 | const { commits, forced, after, repository, ref, compare, sender } = json; 343 | 344 | if (!sender) { 345 | return null; 346 | } 347 | 348 | let branch = ref.substring(11); 349 | 350 | if (env.isIgnoredBranch(branch) || env.isIgnoredUser(sender.login)) { 351 | return null; 352 | } 353 | 354 | if (forced) { 355 | return buildEmbedBody( 356 | env, 357 | `[${repository['full_name']}] Branch ${branch} was force-pushed to \`${shortCommit(after)}\``, 358 | compare.replace('...', '..'), 359 | sender, 360 | 16722234, 361 | ); 362 | } 363 | 364 | let amount = commits.length; 365 | 366 | if (amount === 0) { 367 | return null; 368 | } 369 | 370 | let description = ''; 371 | let lastCommitUrl = ''; 372 | for (let i = 0; i < commits.length; i++) { 373 | let commit = commits[i]; 374 | let commitUrl = commit.url; 375 | let line = `[\`${shortCommit(commit.id)}\`](${commitUrl}) ${truncate(commit.message.split('\n')[0], 50, env.hideDetailsBody)} - ${commit.author.username} 376 | `; 377 | if (description.length + line.length >= 1500) { 378 | break; 379 | } 380 | lastCommitUrl = commitUrl; 381 | description += line; 382 | } 383 | const commitWord = amount === 1 ? 'commit' : 'commits'; 384 | 385 | return buildEmbedBody( 386 | env, 387 | `[${repository.name}:${branch}] ${amount} new ${commitWord}`, 388 | amount === 1 ? lastCommitUrl : compare, 389 | sender, 390 | 6120164, 391 | description, 392 | ); 393 | } 394 | 395 | function buildPullEnqueue( 396 | json: PullRequestEnqueuedWebhookPayload, 397 | env: BoundEnv, 398 | ): string { 399 | const { pull_request, repository, sender } = json; 400 | 401 | const queueUrl = `${repository['html_url']}/queue/${pull_request.base.ref}`; 402 | 403 | return buildEmbedBody( 404 | env, 405 | `[${repository['full_name']}] Pull request enqueued: #${pull_request.number} ${pull_request.title}`, 406 | pull_request['html_url'], 407 | sender, 408 | 16752896, 409 | `[View \`${pull_request.base.ref}\` merge queue](${queueUrl})`, 410 | ); 411 | } 412 | 413 | function buildPullDequeue( 414 | json: PullRequestDequeuedWebhookPayload, 415 | env: BoundEnv, 416 | ): string | null { 417 | const { pull_request, repository, sender } = json; 418 | 419 | // If the pull request is already merged, ignore the dequeue event 420 | // as the merge event will be handled separately. 421 | if (pull_request.merged_at) { 422 | return null; 423 | } 424 | 425 | const queueUrl = `${repository['html_url']}/queue/${pull_request.base.ref}`; 426 | 427 | return buildEmbedBody( 428 | env, 429 | `[${repository['full_name']}] Pull request dequeued: #${pull_request.number} ${pull_request.title}`, 430 | pull_request['html_url'], 431 | sender, 432 | 13584462, 433 | `[View \`${pull_request.base.ref}\` merge queue](${queueUrl})`, 434 | ); 435 | } 436 | 437 | function buildPullReviewComment( 438 | json: PullRequestReviewCommentWebhookPayload, 439 | env: BoundEnv, 440 | ): string { 441 | const { pull_request, comment, repository, sender } = json; 442 | 443 | return buildEmbedBody( 444 | env, 445 | `[${repository['full_name']}] Pull request review comment: #${pull_request.number} ${pull_request.title}`, 446 | comment['html_url'], 447 | sender, 448 | 7829367, 449 | comment.body, 450 | ); 451 | } 452 | 453 | function buildPullReview( 454 | json: 455 | | PullRequestReviewSubmittedWebhookPayload 456 | | PullRequestReviewDismissedWebhookPayload, 457 | env: BoundEnv, 458 | ): string { 459 | const { pull_request, review, repository, action, sender } = json; 460 | 461 | let state = 'reviewed'; 462 | let color = 7829367; 463 | switch (review.state) { 464 | case 'approved': { 465 | state = 'approved'; 466 | color = 37378; 467 | break; 468 | } 469 | case 'changes_requested': { 470 | state = 'changes requested'; 471 | color = 16722234; 472 | break; 473 | } 474 | default: { 475 | if (action === 'dismissed') { 476 | state = 'review dismissed'; 477 | } 478 | break; 479 | } 480 | } 481 | 482 | return buildEmbedBody( 483 | env, 484 | `[${repository['full_name']}] Pull request ${state}: #${pull_request.number} ${pull_request.title}`, 485 | review['html_url'], 486 | sender, 487 | color, 488 | review.body, 489 | ); 490 | } 491 | 492 | function buildPullReadyReview( 493 | json: PullRequestReadyWebhookPayload, 494 | env: BoundEnv, 495 | ): string { 496 | const { pull_request, repository, sender } = json; 497 | 498 | return buildEmbedBody( 499 | env, 500 | `[${repository['full_name']}] Pull request marked for review: #${pull_request.number} ${pull_request.title}`, 501 | pull_request['html_url'], 502 | sender, 503 | 37378, 504 | ); 505 | } 506 | 507 | function buildPullDraft( 508 | json: PullRequestDraftWebhookPayload, 509 | env: BoundEnv, 510 | ): string { 511 | const { pull_request, repository, sender } = json; 512 | 513 | return buildEmbedBody( 514 | env, 515 | `[${repository['full_name']}] Pull request marked as draft: #${pull_request.number} ${pull_request.title}`, 516 | pull_request['html_url'], 517 | sender, 518 | 10987431, 519 | ); 520 | } 521 | 522 | function buildPullReopen( 523 | json: PullRequestReopenedWebhookPayload, 524 | env: BoundEnv, 525 | ): string { 526 | const { pull_request, repository, sender } = json; 527 | 528 | let draft = pull_request.draft; 529 | let color = draft ? 10987431 : 37378; 530 | let type = draft ? 'Draft pull request' : 'Pull request'; 531 | 532 | return buildEmbedBody( 533 | env, 534 | `[${repository['full_name']}] ${type} reopened: #${pull_request.number} ${pull_request.title}`, 535 | pull_request['html_url'], 536 | sender, 537 | color, 538 | ); 539 | } 540 | 541 | function buildPullClose( 542 | json: PullRequestClosedWebhookPayload, 543 | env: BoundEnv, 544 | ): string { 545 | const { pull_request, repository, sender } = json; 546 | 547 | let merged = pull_request.merged; 548 | let color = merged ? 8866047 : 16722234; 549 | let status = merged ? 'merged' : 'closed'; 550 | 551 | return buildEmbedBody( 552 | env, 553 | `[${repository['full_name']}] Pull request ${status}: #${pull_request.number} ${pull_request.title}`, 554 | pull_request['html_url'], 555 | sender, 556 | color, 557 | ); 558 | } 559 | 560 | function buildPull( 561 | json: PullRequestOpenedWebhookPayload, 562 | env: BoundEnv, 563 | ): string | null { 564 | const { pull_request, repository, sender } = json; 565 | 566 | if (env.isIgnoredUser(sender.login)) { 567 | return null; 568 | } 569 | 570 | let draft = pull_request.draft; 571 | let color = draft ? 10987431 : 37378; 572 | let type = draft ? 'Draft pull request' : 'Pull request'; 573 | 574 | return buildEmbedBody( 575 | env, 576 | `[${repository['full_name']}] ${type} opened: #${pull_request.number} ${pull_request.title}`, 577 | pull_request['html_url'], 578 | sender, 579 | color, 580 | pull_request.body, 581 | ); 582 | } 583 | 584 | function buildIssueComment( 585 | json: IssueCommentCreatedWebhookPayload, 586 | env: BoundEnv, 587 | ): string | null { 588 | const { issue, comment, repository, sender } = json; 589 | 590 | if (env.isIgnoredUser(sender.login)) { 591 | return null; 592 | } 593 | 594 | let entity = 'pull_request' in issue ? 'pull request' : 'issue'; 595 | 596 | return buildEmbedBody( 597 | env, 598 | `[${repository['full_name']}] New comment on ${entity}: #${issue.number} ${issue.title}`, 599 | comment['html_url'], 600 | sender, 601 | 11373312, 602 | comment.body, 603 | ); 604 | } 605 | 606 | function buildIssueClose( 607 | json: IssueClosedWebhookPayload, 608 | env: BoundEnv, 609 | ): string { 610 | const { issue, repository, sender } = json; 611 | 612 | const reason = issue.state_reason; 613 | 614 | return buildEmbedBody( 615 | env, 616 | `[${repository['full_name']}] Issue closed ${reason ? `as ${reason.replaceAll('_', ' ')}` : ''}: #${issue.number} ${issue.title}`, 617 | issue['html_url'], 618 | sender, 619 | 16730159, 620 | ); 621 | } 622 | 623 | function buildIssueReOpen( 624 | json: IssueReopenedWebhookPayload, 625 | env: BoundEnv, 626 | ): string { 627 | const { issue, repository, sender } = json; 628 | 629 | return buildEmbedBody( 630 | env, 631 | `[${repository['full_name']}] Issue reopened: #${issue.number} ${issue.title}`, 632 | issue['html_url'], 633 | sender, 634 | 16743680, 635 | ); 636 | } 637 | 638 | function buildIssue( 639 | json: IssueCreatedWebhookPayload, 640 | env: BoundEnv, 641 | ): string | null { 642 | const { issue, repository, sender } = json; 643 | 644 | if (env.isIgnoredUser(sender.login)) { 645 | return null; 646 | } 647 | 648 | return buildEmbedBody( 649 | env, 650 | `[${repository['full_name']}] Issue opened: #${issue.number} ${issue.title}`, 651 | issue['html_url'], 652 | sender, 653 | 16743680, 654 | issue.body, 655 | ); 656 | } 657 | 658 | function buildPackagePublished( 659 | json: PackagePublishedWebhookPayload, 660 | env: BoundEnv, 661 | ): string | null { 662 | const { sender, repository } = json; 663 | if (!repository) { 664 | return null; 665 | } 666 | 667 | const pkg = 'package' in json ? json.package : json['registry_package']; 668 | 669 | return buildEmbedBody( 670 | env, 671 | `[${repository['full_name']}] Package Published: ${pkg.namespace}/${pkg.name}`, 672 | pkg['package_version']?.['html_url'], 673 | sender, 674 | 37378, 675 | ); 676 | } 677 | 678 | function buildPackageUpdated( 679 | json: PackageUpdatedWebhookPayload, 680 | env: BoundEnv, 681 | ): string { 682 | const { sender, repository } = json; 683 | const pkg = 'package' in json ? json.package : json['registry_package']; 684 | 685 | return buildEmbedBody( 686 | env, 687 | `[${repository['full_name']}] Package Updated: ${pkg.namespace}/${pkg.name}`, 688 | pkg['package_version']['html_url'], 689 | sender, 690 | 37378, 691 | ); 692 | } 693 | 694 | function buildFork(json: ForkWebhookPayload, env: BoundEnv): string { 695 | const { sender, repository, forkee } = json; 696 | 697 | return buildEmbedBody( 698 | env, 699 | `[${repository['full_name']}] Fork Created: ${forkee['full_name']}`, 700 | forkee['html_url'], 701 | sender, 702 | 16562432, 703 | ); 704 | } 705 | 706 | function buildDiscussionComment( 707 | json: DiscussionCommentCreatedWebhookPayload, 708 | env: BoundEnv, 709 | ): string | null { 710 | const { discussion, comment, repository, sender } = json; 711 | const { category } = discussion; 712 | 713 | if (env.isIgnoredUser(sender.login)) { 714 | return null; 715 | } 716 | 717 | return buildEmbedBody( 718 | env, 719 | `[${repository['full_name']}] New comment on discussion: #${discussion.number} ${discussion.title}`, 720 | comment['html_url'], 721 | sender, 722 | 35446, 723 | comment.body, 724 | `Discussion Category: ${category.name}`, 725 | ); 726 | } 727 | 728 | function buildDiscussion( 729 | json: DiscussionCreatedWebhookPayload, 730 | env: BoundEnv, 731 | ): string | null { 732 | const { discussion, repository, sender } = json; 733 | const { category } = discussion; 734 | 735 | if (env.isIgnoredUser(sender.login)) { 736 | return null; 737 | } 738 | 739 | return buildEmbedBody( 740 | env, 741 | `[${repository['full_name']}] New discussion: #${discussion.number} ${discussion.title}`, 742 | discussion['html_url'], 743 | sender, 744 | 9737471, 745 | discussion.body, 746 | `Discussion Category: ${category.name}`, 747 | ); 748 | } 749 | 750 | function buildDeleteBranch( 751 | json: BranchDeletedWebhookPayload, 752 | env: BoundEnv, 753 | ): string | null { 754 | const { ref, ref_type, repository, sender } = json; 755 | 756 | if (ref_type == 'branch' && env.isIgnoredBranch(ref)) { 757 | return null; 758 | } 759 | 760 | return buildEmbedBody( 761 | env, 762 | `[${repository['full_name']}] ${ref_type} deleted: ${ref}`, 763 | undefined, 764 | sender, 765 | 1, 766 | ); 767 | } 768 | 769 | function buildCreateBranch( 770 | json: BranchCreatedWebhookPayload, 771 | env: BoundEnv, 772 | ): string | null { 773 | const { ref, ref_type, repository, sender } = json; 774 | 775 | if (env.isIgnoredUser(sender.login)) { 776 | return null; 777 | } 778 | 779 | if (ref_type == 'branch' && env.isIgnoredBranch(ref)) { 780 | return null; 781 | } 782 | 783 | return buildEmbedBody( 784 | env, 785 | `[${repository['full_name']}] New ${ref_type} created: ${ref}`, 786 | undefined, 787 | sender, 788 | 3881787, 789 | ); 790 | } 791 | 792 | function buildCommitComment( 793 | json: CommitCommentCreatedWebhookPayload, 794 | env: BoundEnv, 795 | ): string | null { 796 | const { sender, comment, repository } = json; 797 | 798 | if (env.isIgnoredUser(sender.login)) { 799 | return null; 800 | } 801 | 802 | return buildEmbedBody( 803 | env, 804 | `[${repository['full_name']}] New comment on commit \`${shortCommit(comment['commit_id'])}\``, 805 | comment['html_url'], 806 | sender, 807 | 3881787, 808 | comment.body, 809 | ); 810 | } 811 | 812 | function buildCheck( 813 | json: CheckRunCompletedWebhookPayload, 814 | env: BoundEnv, 815 | ): string | null { 816 | const { check_run, repository, sender } = json; 817 | const { conclusion, output, html_url, check_suite } = check_run; 818 | 819 | if (repository == null || check_suite['head_branch'] == null) { 820 | return null; 821 | } 822 | 823 | let target = check_suite['head_branch']; 824 | 825 | if (env.isIgnoredBranch(target)) { 826 | return null; 827 | } 828 | 829 | if (check_suite.pull_requests && check_suite.pull_requests.length > 0) { 830 | let pull = check_suite['pull_requests'][0]; 831 | if ( 832 | pull.url.startsWith( 833 | `https://api.github.com/repos/${repository['full_name']}`, 834 | ) 835 | ) { 836 | target = `PR #${pull.number}`; 837 | } 838 | } 839 | 840 | let color = 11184810; 841 | let status = 'failed'; 842 | if (conclusion === 'success') { 843 | color = 45866; 844 | status = 'succeeded'; 845 | } else if (conclusion === 'failure' || conclusion === 'cancelled') { 846 | color = 16726843; 847 | status = conclusion === 'failure' ? 'failed' : 'cancelled'; 848 | } else if ( 849 | conclusion === 'timed_out' || 850 | conclusion === 'action_required' || 851 | conclusion === 'stale' 852 | ) { 853 | color = 14984995; 854 | status = 855 | conclusion === 'timed_out' ? 'timed out' 856 | : conclusion === 'action_required' ? 'requires action' 857 | : 'became stale'; 858 | } else if (conclusion === 'neutral') { 859 | status = "didn't run"; 860 | } else if (conclusion === 'skipped') { 861 | status = 'was skipped'; 862 | } 863 | 864 | let fields = [ 865 | { 866 | name: 'Action Name', 867 | value: check_run.name, 868 | inline: true, 869 | }, 870 | ]; 871 | 872 | if (output.title != null) { 873 | fields.push({ 874 | name: 'Output Title', 875 | value: truncate(output.title, 1000, env.hideDetailsBody)!, 876 | inline: true, 877 | }); 878 | } 879 | 880 | if (output.summary != null) { 881 | fields.push({ 882 | name: 'Output Summary', 883 | value: truncate(output.summary, 1000, env.hideDetailsBody)!, 884 | inline: false, 885 | }); 886 | } 887 | 888 | return buildEmbedBody( 889 | env, 890 | `[${repository['full_name']}] Actions check ${status} on ${target}`, 891 | html_url, 892 | sender, 893 | color, 894 | undefined, 895 | undefined, 896 | fields, 897 | ); 898 | } 899 | 900 | function buildStar(json: StarCreatedWebhookPayload, env: BoundEnv): string { 901 | const { sender, repository } = json; 902 | 903 | return buildEmbedBody( 904 | env, 905 | `[${repository['full_name']}] New star added`, 906 | repository['html_url'], 907 | sender, 908 | 16562432, 909 | ); 910 | } 911 | 912 | function buildDeployment(json: DeploymentCreatedWebhookPayload, env: BoundEnv) { 913 | const { deployment, repository, sender } = json; 914 | const { description } = deployment; 915 | 916 | const payload = deployment['payload'] as any; 917 | 918 | return buildEmbedBody( 919 | env, 920 | `[${repository['full_name']}] Deployment started for ${description}`, 921 | payload['web_url'] === null ? '' : payload['web_url'], 922 | sender, 923 | 11158713, 924 | ); 925 | } 926 | 927 | function buildDeploymentStatus( 928 | json: DeploymentStatusCreatedWebhookPayload, 929 | env: BoundEnv, 930 | ) { 931 | const { deployment, deployment_status, repository, sender } = json; 932 | const { description } = deployment; 933 | const { state } = deployment_status; 934 | 935 | let color = 16726843; 936 | let term = 'succeeded'; 937 | switch (state) { 938 | case 'success': { 939 | color = 45866; 940 | break; 941 | } 942 | case 'failure': { 943 | term = 'failed'; 944 | break; 945 | } 946 | case 'error': { 947 | term = 'errored'; 948 | break; 949 | } 950 | default: { 951 | return null; 952 | } 953 | } 954 | 955 | const payload = deployment['payload'] as any; 956 | 957 | return buildEmbedBody( 958 | env, 959 | `[${repository['full_name']}] Deployment for ${description} ${term}`, 960 | payload['web_url'] === null ? '' : payload['web_url'], 961 | sender, 962 | color, 963 | ); 964 | } 965 | 966 | function buildWiki(json: WikiWebhookPayload, env: BoundEnv): string | null { 967 | const { pages, sender, repository } = json; 968 | 969 | // Pages is always an array with several "actions". 970 | // Count the amount of "created" and "edited" actions and store the amount in a variable. 971 | // Also store the titles of the pages in an array since we will need them later. 972 | let created = 0; 973 | let edited = 0; 974 | let titles: string[] = []; 975 | for (let i = 0; i < pages.length; i++) { 976 | const { action } = pages[i]; 977 | if (action === 'created') { 978 | created++; 979 | } else if (action === 'edited') { 980 | edited++; 981 | } 982 | 983 | // Wrap the title in a markdown with the link to the page. 984 | let title = `[${pages[i].title}](${pages[i]['html_url']})`; 985 | 986 | // Capitalize the first letter of the action, then prepend it to the title. 987 | titles.push( 988 | `${action.charAt(0).toUpperCase() + action.slice(1)}: ${title}`, 989 | ); 990 | } 991 | 992 | // If there are no pages, return null. 993 | if (created === 0 && edited === 0) { 994 | return null; 995 | } 996 | 997 | // Set the message based on if there are any created or edited pages. 998 | // If there are only 1 of one type, set the message to singular. 999 | // If there are multiple of one type, set the message to plural. 1000 | let message; 1001 | let color; 1002 | if (created === 1 && edited === 0) { 1003 | message = 'A page was created'; 1004 | // Set the color to green. 1005 | color = 45866; 1006 | } else if (created === 0 && edited === 1) { 1007 | message = 'A page was edited'; 1008 | // Set the color to orange. 1009 | color = 16562432; 1010 | } else { 1011 | if (created > 0 && edited > 0) { 1012 | message = `${created} page${created > 1 ? 's' : ''} were created and ${edited} ${edited > 1 ? 'were' : 'was'} edited`; 1013 | } else { 1014 | message = `${Math.max(created, edited)} pages were ${created > 0 ? 'created' : 'edited'}`; 1015 | } 1016 | // Set the color to blue. 1017 | color = 6120164; 1018 | } 1019 | 1020 | // Prepend the repository title to the message. 1021 | message = `[${repository['full_name']}] ${message}`; 1022 | 1023 | // Build the embed, with the sender as the author, the message as the title, and the edited pages as the description. 1024 | return buildEmbedBody( 1025 | env, 1026 | message, 1027 | repository['html_url'], 1028 | sender, 1029 | color, 1030 | titles.join('\n'), 1031 | ); 1032 | } 1033 | 1034 | function handleError(error: any): Response { 1035 | console.error('Uncaught error:', error); 1036 | 1037 | const { stack } = error; 1038 | return new Response(stack || error, { 1039 | status: 500, 1040 | headers: { 1041 | 'Content-Type': 'text/plain;charset=UTF-8', 1042 | }, 1043 | }); 1044 | } 1045 | 1046 | export default { 1047 | async fetch( 1048 | request: Request, 1049 | env: Env, 1050 | _: ExecutionContext, 1051 | ): Promise { 1052 | const url = new URL(request.url); 1053 | if (url.pathname === '/health') { 1054 | return new Response('OK', { status: 200 }); 1055 | } 1056 | 1057 | const bound = new BoundEnv(env); 1058 | return handleRequest(request, bound).catch(handleError); 1059 | }, 1060 | }; 1061 | -------------------------------------------------------------------------------- /bun.lock: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1, 3 | "workspaces": { 4 | "": { 5 | "name": "disgit", 6 | "dependencies": { 7 | "@cloudflare/workers-types": "^4.20250607.0", 8 | "@octokit/openapi-webhooks-types": "^12.0.3", 9 | "typescript": "^5.8.3", 10 | "wrangler": "^4.19.1", 11 | }, 12 | "devDependencies": { 13 | "@eslint/eslintrc": "^3.3.1", 14 | "@eslint/js": "^9.30.1", 15 | "eslint": "^9.28.0", 16 | "eslint-config-prettier": "^10.1.5", 17 | "eslint-plugin-prettier": "^5.4.1", 18 | "prettier": "^3.6.2", 19 | "prettier-plugin-organize-imports": "^4.1.0", 20 | "selflare": "^1.1.2", 21 | }, 22 | }, 23 | }, 24 | "packages": { 25 | "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="], 26 | 27 | "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.3.2", "", { "peerDependencies": { "unenv": "2.0.0-rc.17", "workerd": "^1.20250508.0" }, "optionalPeers": ["workerd"] }, "sha512-MtUgNl+QkQyhQvv5bbWP+BpBC1N0me4CHHuP2H4ktmOMKdB/6kkz/lo+zqiA4mEazb4y+1cwyNjVrQ2DWeE4mg=="], 28 | 29 | "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250607.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZPEYltIzDbGYlSZFcAyVnbFxZeG9xlmGmz4742C7tvZ8fOrqXExdqnqPwE1anIRLKx/Oxt/nemPng+V2iSrPUw=="], 30 | 31 | "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250607.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-AC4bH9u8RF97szBM5KNXO6jRHbeat8CX4Cm+T3IANSkHAMkVRi5wjjnCy1teF3TBrXSRB5epvH8y7jTBQjJpLQ=="], 32 | 33 | "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250607.0", "", { "os": "linux", "cpu": "x64" }, "sha512-floRxUocnj4+ULmIsIRFwzxzRTarvidD0tLpSS3HjyuTUy5ma+pgAyfXQcE3oP8orBJlG5QIOtgVDpH4jD1qTQ=="], 34 | 35 | "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250607.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-w4ghOr5eof/rnpuW1XJwwuLOReVumAt8SrRv66aZB7ly7eBpfnOCZIaa4obZ9uuEbonxblHXUyVfBMgjL6u52w=="], 36 | 37 | "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250607.0", "", { "os": "win32", "cpu": "x64" }, "sha512-fKp/Cgh4LG2XiqiVShGENVqZ+nZ6B19y3cqf2tRuHVPgRQgnYnEDneS8jJTkltC0gKJNp+cLawEe8DSDbQJ7Vg=="], 38 | 39 | "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250607.0", "", {}, "sha512-OYmKNzC2eQy6CNj+j0go8Ut3SezjsprCgJyEaBzJql+473WAN9ndVnNZy9lj/tTyLV6wzpQkZWmRAKGDmacvkg=="], 40 | 41 | "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], 42 | 43 | "@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="], 44 | 45 | "@esbuild-plugins/node-globals-polyfill": ["@esbuild-plugins/node-globals-polyfill@0.2.3", "", { "peerDependencies": { "esbuild": "*" } }, "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw=="], 46 | 47 | "@esbuild-plugins/node-modules-polyfill": ["@esbuild-plugins/node-modules-polyfill@0.2.2", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "rollup-plugin-node-polyfills": "^0.2.1" }, "peerDependencies": { "esbuild": "*" } }, "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA=="], 48 | 49 | "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], 50 | 51 | "@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], 52 | 53 | "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.4", "", { "os": "android", "cpu": "arm64" }, "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A=="], 54 | 55 | "@esbuild/android-x64": ["@esbuild/android-x64@0.25.4", "", { "os": "android", "cpu": "x64" }, "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ=="], 56 | 57 | "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g=="], 58 | 59 | "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A=="], 60 | 61 | "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ=="], 62 | 63 | "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ=="], 64 | 65 | "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.4", "", { "os": "linux", "cpu": "arm" }, "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ=="], 66 | 67 | "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ=="], 68 | 69 | "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ=="], 70 | 71 | "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA=="], 72 | 73 | "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg=="], 74 | 75 | "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag=="], 76 | 77 | "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA=="], 78 | 79 | "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g=="], 80 | 81 | "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA=="], 82 | 83 | "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.4", "", { "os": "none", "cpu": "arm64" }, "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ=="], 84 | 85 | "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.4", "", { "os": "none", "cpu": "x64" }, "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw=="], 86 | 87 | "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A=="], 88 | 89 | "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], 90 | 91 | "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], 92 | 93 | "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], 94 | 95 | "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], 96 | 97 | "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], 98 | 99 | "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], 100 | 101 | "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], 102 | 103 | "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], 104 | 105 | "@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="], 106 | 107 | "@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="], 108 | 109 | "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], 110 | 111 | "@eslint/js": ["@eslint/js@9.32.0", "", {}, "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg=="], 112 | 113 | "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], 114 | 115 | "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.4", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw=="], 116 | 117 | "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], 118 | 119 | "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], 120 | 121 | "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], 122 | 123 | "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], 124 | 125 | "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], 126 | 127 | "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], 128 | 129 | "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], 130 | 131 | "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], 132 | 133 | "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], 134 | 135 | "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], 136 | 137 | "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], 138 | 139 | "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], 140 | 141 | "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], 142 | 143 | "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], 144 | 145 | "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], 146 | 147 | "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], 148 | 149 | "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], 150 | 151 | "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], 152 | 153 | "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], 154 | 155 | "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], 156 | 157 | "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], 158 | 159 | "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], 160 | 161 | "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], 162 | 163 | "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], 164 | 165 | "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], 166 | 167 | "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], 168 | 169 | "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], 170 | 171 | "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], 172 | 173 | "@octokit/openapi-webhooks-types": ["@octokit/openapi-webhooks-types@12.0.3", "", {}, "sha512-90MF5LVHjBedwoHyJsgmaFhEN1uzXyBDRLEBe7jlTYx/fEhPAk3P3DAJsfZwC54m8hAIryosJOL+UuZHB3K3yA=="], 174 | 175 | "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], 176 | 177 | "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], 178 | 179 | "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 180 | 181 | "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], 182 | 183 | "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], 184 | 185 | "acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="], 186 | 187 | "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], 188 | 189 | "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], 190 | 191 | "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], 192 | 193 | "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], 194 | 195 | "as-table": ["as-table@1.0.55", "", { "dependencies": { "printable-characters": "^1.0.42" } }, "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ=="], 196 | 197 | "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 198 | 199 | "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], 200 | 201 | "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], 202 | 203 | "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 204 | 205 | "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 206 | 207 | "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], 208 | 209 | "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], 210 | 211 | "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 212 | 213 | "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 214 | 215 | "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], 216 | 217 | "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 218 | 219 | "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], 220 | 221 | "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], 222 | 223 | "data-uri-to-buffer": ["data-uri-to-buffer@2.0.2", "", {}, "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="], 224 | 225 | "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], 226 | 227 | "dedent": ["dedent@1.6.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA=="], 228 | 229 | "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 230 | 231 | "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], 232 | 233 | "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], 234 | 235 | "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], 236 | 237 | "esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], 238 | 239 | "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], 240 | 241 | "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], 242 | 243 | "eslint": ["eslint@9.32.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.32.0", "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg=="], 244 | 245 | "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], 246 | 247 | "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.3", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w=="], 248 | 249 | "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], 250 | 251 | "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], 252 | 253 | "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], 254 | 255 | "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], 256 | 257 | "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], 258 | 259 | "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], 260 | 261 | "estree-walker": ["estree-walker@0.6.1", "", {}, "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="], 262 | 263 | "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], 264 | 265 | "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], 266 | 267 | "exsolve": ["exsolve@1.0.5", "", {}, "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="], 268 | 269 | "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], 270 | 271 | "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], 272 | 273 | "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], 274 | 275 | "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], 276 | 277 | "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], 278 | 279 | "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], 280 | 281 | "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], 282 | 283 | "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], 284 | 285 | "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 286 | 287 | "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], 288 | 289 | "get-source": ["get-source@2.0.12", "", { "dependencies": { "data-uri-to-buffer": "^2.0.0", "source-map": "^0.6.1" } }, "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w=="], 290 | 291 | "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 292 | 293 | "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], 294 | 295 | "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], 296 | 297 | "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], 298 | 299 | "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], 300 | 301 | "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], 302 | 303 | "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 304 | 305 | "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], 306 | 307 | "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 308 | 309 | "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], 310 | 311 | "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 312 | 313 | "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], 314 | 315 | "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], 316 | 317 | "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], 318 | 319 | "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 320 | 321 | "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], 322 | 323 | "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 324 | 325 | "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 326 | 327 | "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], 328 | 329 | "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], 330 | 331 | "magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="], 332 | 333 | "mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], 334 | 335 | "miniflare": ["miniflare@4.20250525.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250525.0", "ws": "8.18.0", "youch": "3.3.4", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-4PJlT5WA+hfclFU5Q7xnpG1G1VGYTXaf/3iu6iKQ8IsbSi9QvPTA2bSZ5goCFxmJXDjV4cxttVxB0Wl1CLuQ0w=="], 336 | 337 | "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 338 | 339 | "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], 340 | 341 | "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], 342 | 343 | "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], 344 | 345 | "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], 346 | 347 | "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], 348 | 349 | "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], 350 | 351 | "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], 352 | 353 | "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], 354 | 355 | "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], 356 | 357 | "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], 358 | 359 | "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], 360 | 361 | "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 362 | 363 | "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], 364 | 365 | "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], 366 | 367 | "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], 368 | 369 | "prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@4.2.0", "", { "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", "vue-tsc": "^2.1.0 || 3" }, "optionalPeers": ["vue-tsc"] }, "sha512-Zdy27UhlmyvATZi67BTnLcKTo8fm6Oik59Sz6H64PgZJVs6NJpPD1mT240mmJn62c98/QaL+r3kx9Q3gRpDajg=="], 370 | 371 | "printable-characters": ["printable-characters@1.0.42", "", {}, "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="], 372 | 373 | "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], 374 | 375 | "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], 376 | 377 | "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], 378 | 379 | "rollup-plugin-inject": ["rollup-plugin-inject@3.0.2", "", { "dependencies": { "estree-walker": "^0.6.1", "magic-string": "^0.25.3", "rollup-pluginutils": "^2.8.1" } }, "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w=="], 380 | 381 | "rollup-plugin-node-polyfills": ["rollup-plugin-node-polyfills@0.2.1", "", { "dependencies": { "rollup-plugin-inject": "^3.0.0" } }, "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA=="], 382 | 383 | "rollup-pluginutils": ["rollup-pluginutils@2.8.2", "", { "dependencies": { "estree-walker": "^0.6.1" } }, "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ=="], 384 | 385 | "selflare": ["selflare@1.1.2", "", { "dependencies": { "@iarna/toml": "^2.2.5", "dedent": "^1.5.1", "workerd": "^1.20240223.1", "wrangler": "^3.30.1", "yargs": "^17.7.2" }, "bin": { "selflare": "dist/index.js" } }, "sha512-i3nasf4rzAt5g3qmcmnjoxQHFsZ/u9+KJ8LZqFhV0PEkFngMwicpoMDXtwNngID8TuZss/dex+RZ9ZcFGODoiA=="], 386 | 387 | "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], 388 | 389 | "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], 390 | 391 | "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 392 | 393 | "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], 394 | 395 | "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], 396 | 397 | "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 398 | 399 | "sourcemap-codec": ["sourcemap-codec@1.4.8", "", {}, "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="], 400 | 401 | "stacktracey": ["stacktracey@2.1.8", "", { "dependencies": { "as-table": "^1.0.36", "get-source": "^2.0.12" } }, "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw=="], 402 | 403 | "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], 404 | 405 | "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], 406 | 407 | "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], 408 | 409 | "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], 410 | 411 | "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 412 | 413 | "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], 414 | 415 | "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 416 | 417 | "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], 418 | 419 | "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], 420 | 421 | "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], 422 | 423 | "undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], 424 | 425 | "unenv": ["unenv@2.0.0-rc.17", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" } }, "sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg=="], 426 | 427 | "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], 428 | 429 | "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 430 | 431 | "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 432 | 433 | "workerd": ["workerd@1.20250607.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250607.0", "@cloudflare/workerd-darwin-arm64": "1.20250607.0", "@cloudflare/workerd-linux-64": "1.20250607.0", "@cloudflare/workerd-linux-arm64": "1.20250607.0", "@cloudflare/workerd-windows-64": "1.20250607.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-STF1R9iySmM8XgSWQP1v0Jp9wxzZzH8p369CGHsFdlOUgtMbRmD5ssQxv9Z5PnZQ+L/c+kiioUxPR3ROC3AKwA=="], 434 | 435 | "wrangler": ["wrangler@4.19.1", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.3.2", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250525.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.17", "workerd": "1.20250525.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250525.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-b+ed2SJKauHgndl4Im1wHE+FeSSlrdlEZNuvpc8q/94k4EmRxRkXnwBAsVWuicBxG3HStFLQPGGlvL8wGKTtHw=="], 436 | 437 | "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], 438 | 439 | "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], 440 | 441 | "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], 442 | 443 | "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], 444 | 445 | "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], 446 | 447 | "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 448 | 449 | "youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="], 450 | 451 | "zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], 452 | 453 | "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], 454 | 455 | "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], 456 | 457 | "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], 458 | 459 | "miniflare/workerd": ["workerd@1.20250525.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250525.0", "@cloudflare/workerd-darwin-arm64": "1.20250525.0", "@cloudflare/workerd-linux-64": "1.20250525.0", "@cloudflare/workerd-linux-arm64": "1.20250525.0", "@cloudflare/workerd-windows-64": "1.20250525.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-SXJgLREy/Aqw2J71Oah0Pbu+SShbqbTExjVQyRBTM1r7MG7fS5NUlknhnt6sikjA/t4cO09Bi8OJqHdTkrcnYQ=="], 460 | 461 | "selflare/wrangler": ["wrangler@3.114.9", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.3.4", "@cloudflare/unenv-preset": "2.0.2", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@esbuild-plugins/node-modules-polyfill": "0.2.2", "blake3-wasm": "2.1.5", "esbuild": "0.17.19", "miniflare": "3.20250408.2", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.14", "workerd": "1.20250408.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250408.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-1e0gL+rxLF04kM9bW4sxoDGLXpJ1x53Rx1t18JuUm6F67qadKKPISyUAXuBeIQudWrCWEBXaTVnSdLHz0yBXbA=="], 462 | 463 | "wrangler/workerd": ["workerd@1.20250525.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250525.0", "@cloudflare/workerd-darwin-arm64": "1.20250525.0", "@cloudflare/workerd-linux-64": "1.20250525.0", "@cloudflare/workerd-linux-arm64": "1.20250525.0", "@cloudflare/workerd-windows-64": "1.20250525.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-SXJgLREy/Aqw2J71Oah0Pbu+SShbqbTExjVQyRBTM1r7MG7fS5NUlknhnt6sikjA/t4cO09Bi8OJqHdTkrcnYQ=="], 464 | 465 | "miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250525.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-L5l+7sSJJT2+riR5rS3Q3PKNNySPjWfRIeaNGMVRi1dPO6QPi4lwuxfRUFNoeUdilZJUVPfSZvTtj9RedsKznQ=="], 466 | 467 | "miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250525.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y3IbIdrF/vJWh/WBvshwcSyUh175VAiLRW7963S1dXChrZ1N5wuKGQm9xY69cIGVtitpMJWWW3jLq7J/Xxwm0Q=="], 468 | 469 | "miniflare/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250525.0", "", { "os": "linux", "cpu": "x64" }, "sha512-KSyQPAby+c6cpENoO0ayCQlY6QIh28l/+QID7VC1SLXfiNHy+hPNsH1vVBTST6CilHVAQSsy9tCZ9O9XECB8yg=="], 470 | 471 | "miniflare/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250525.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nt0FUxS2kQhJUea4hMCNPaetkrAFDhPnNX/ntwcqVlGgnGt75iaAhupWJbU0GB+gIWlKeuClUUnDZqKbicoKyg=="], 472 | 473 | "miniflare/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250525.0", "", { "os": "win32", "cpu": "x64" }, "sha512-mwTj+9f3uIa4NEXR1cOa82PjLa6dbrb3J+KCVJFYIaq7e63VxEzOchCXS4tublT2pmOhmFqkgBMXrxozxNkR2Q=="], 474 | 475 | "selflare/wrangler/@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.3.4", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q=="], 476 | 477 | "selflare/wrangler/@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.0.2", "", { "peerDependencies": { "unenv": "2.0.0-rc.14", "workerd": "^1.20250124.0" }, "optionalPeers": ["workerd"] }, "sha512-nyzYnlZjjV5xT3LizahG1Iu6mnrCaxglJ04rZLpDwlDVDZ7v46lNsfxhV3A/xtfgQuSHmLnc6SVI+KwBpc3Lwg=="], 478 | 479 | "selflare/wrangler/esbuild": ["esbuild@0.17.19", "", { "optionalDependencies": { "@esbuild/android-arm": "0.17.19", "@esbuild/android-arm64": "0.17.19", "@esbuild/android-x64": "0.17.19", "@esbuild/darwin-arm64": "0.17.19", "@esbuild/darwin-x64": "0.17.19", "@esbuild/freebsd-arm64": "0.17.19", "@esbuild/freebsd-x64": "0.17.19", "@esbuild/linux-arm": "0.17.19", "@esbuild/linux-arm64": "0.17.19", "@esbuild/linux-ia32": "0.17.19", "@esbuild/linux-loong64": "0.17.19", "@esbuild/linux-mips64el": "0.17.19", "@esbuild/linux-ppc64": "0.17.19", "@esbuild/linux-riscv64": "0.17.19", "@esbuild/linux-s390x": "0.17.19", "@esbuild/linux-x64": "0.17.19", "@esbuild/netbsd-x64": "0.17.19", "@esbuild/openbsd-x64": "0.17.19", "@esbuild/sunos-x64": "0.17.19", "@esbuild/win32-arm64": "0.17.19", "@esbuild/win32-ia32": "0.17.19", "@esbuild/win32-x64": "0.17.19" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw=="], 480 | 481 | "selflare/wrangler/miniflare": ["miniflare@3.20250408.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250408.0", "ws": "8.18.0", "youch": "3.3.4", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-uTs7cGWFErgJTKtBdmtctwhuoxniuCQqDT8+xaEiJdEC8d+HsaZVYfZwIX2NuSmdAiHMe7NtbdZYjFMbIXtJsQ=="], 482 | 483 | "selflare/wrangler/unenv": ["unenv@2.0.0-rc.14", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.1", "ohash": "^2.0.10", "pathe": "^2.0.3", "ufo": "^1.5.4" } }, "sha512-od496pShMen7nOy5VmVJCnq8rptd45vh6Nx/r2iPbrba6pa6p+tS2ywuIHRZ/OBvSbQZB0kWvpO9XBNVFXHD3Q=="], 484 | 485 | "selflare/wrangler/workerd": ["workerd@1.20250408.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250408.0", "@cloudflare/workerd-darwin-arm64": "1.20250408.0", "@cloudflare/workerd-linux-64": "1.20250408.0", "@cloudflare/workerd-linux-arm64": "1.20250408.0", "@cloudflare/workerd-windows-64": "1.20250408.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-bBUX+UsvpzAqiWFNeZrlZmDGddiGZdBBbftZJz2wE6iUg/cIAJeVQYTtS/3ahaicguoLBz4nJiDo8luqM9fx1A=="], 486 | 487 | "wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250525.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-L5l+7sSJJT2+riR5rS3Q3PKNNySPjWfRIeaNGMVRi1dPO6QPi4lwuxfRUFNoeUdilZJUVPfSZvTtj9RedsKznQ=="], 488 | 489 | "wrangler/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250525.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y3IbIdrF/vJWh/WBvshwcSyUh175VAiLRW7963S1dXChrZ1N5wuKGQm9xY69cIGVtitpMJWWW3jLq7J/Xxwm0Q=="], 490 | 491 | "wrangler/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250525.0", "", { "os": "linux", "cpu": "x64" }, "sha512-KSyQPAby+c6cpENoO0ayCQlY6QIh28l/+QID7VC1SLXfiNHy+hPNsH1vVBTST6CilHVAQSsy9tCZ9O9XECB8yg=="], 492 | 493 | "wrangler/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250525.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nt0FUxS2kQhJUea4hMCNPaetkrAFDhPnNX/ntwcqVlGgnGt75iaAhupWJbU0GB+gIWlKeuClUUnDZqKbicoKyg=="], 494 | 495 | "wrangler/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250525.0", "", { "os": "win32", "cpu": "x64" }, "sha512-mwTj+9f3uIa4NEXR1cOa82PjLa6dbrb3J+KCVJFYIaq7e63VxEzOchCXS4tublT2pmOhmFqkgBMXrxozxNkR2Q=="], 496 | 497 | "selflare/wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.17.19", "", { "os": "android", "cpu": "arm" }, "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A=="], 498 | 499 | "selflare/wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.17.19", "", { "os": "android", "cpu": "arm64" }, "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA=="], 500 | 501 | "selflare/wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.17.19", "", { "os": "android", "cpu": "x64" }, "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww=="], 502 | 503 | "selflare/wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.17.19", "", { "os": "darwin", "cpu": "arm64" }, "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg=="], 504 | 505 | "selflare/wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.17.19", "", { "os": "darwin", "cpu": "x64" }, "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw=="], 506 | 507 | "selflare/wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.17.19", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ=="], 508 | 509 | "selflare/wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.17.19", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ=="], 510 | 511 | "selflare/wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.17.19", "", { "os": "linux", "cpu": "arm" }, "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA=="], 512 | 513 | "selflare/wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.17.19", "", { "os": "linux", "cpu": "arm64" }, "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg=="], 514 | 515 | "selflare/wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.17.19", "", { "os": "linux", "cpu": "ia32" }, "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ=="], 516 | 517 | "selflare/wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ=="], 518 | 519 | "selflare/wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A=="], 520 | 521 | "selflare/wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.17.19", "", { "os": "linux", "cpu": "ppc64" }, "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg=="], 522 | 523 | "selflare/wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA=="], 524 | 525 | "selflare/wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.17.19", "", { "os": "linux", "cpu": "s390x" }, "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q=="], 526 | 527 | "selflare/wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.17.19", "", { "os": "linux", "cpu": "x64" }, "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw=="], 528 | 529 | "selflare/wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.17.19", "", { "os": "none", "cpu": "x64" }, "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q=="], 530 | 531 | "selflare/wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.17.19", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g=="], 532 | 533 | "selflare/wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.17.19", "", { "os": "sunos", "cpu": "x64" }, "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg=="], 534 | 535 | "selflare/wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.17.19", "", { "os": "win32", "cpu": "arm64" }, "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag=="], 536 | 537 | "selflare/wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.17.19", "", { "os": "win32", "cpu": "ia32" }, "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw=="], 538 | 539 | "selflare/wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.17.19", "", { "os": "win32", "cpu": "x64" }, "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA=="], 540 | 541 | "selflare/wrangler/miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], 542 | 543 | "selflare/wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250408.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-bxhIwBWxaNItZLXDNOKY2dCv0FHjDiDkfJFpwv4HvtvU5MKcrivZHVmmfDzLW85rqzfcDOmKbZeMPVfiKxdBZw=="], 544 | 545 | "selflare/wrangler/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250408.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5XZ2Oykr8bSo7zBmERtHh18h5BZYC/6H1YFWVxEj3PtalF3+6SHsO4KZsbGvDml9Pu7sHV277jiZE5eny8Hlyw=="], 546 | 547 | "selflare/wrangler/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250408.0", "", { "os": "linux", "cpu": "x64" }, "sha512-WbgItXWln6G5d7GvYLWcuOzAVwafysZaWunH3UEfsm95wPuRofpYnlDD861gdWJX10IHSVgMStGESUcs7FLerQ=="], 548 | 549 | "selflare/wrangler/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250408.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-pAhEywPPvr92SLylnQfZEPgXz+9pOG9G9haAPLpEatncZwYiYd9yiR6HYWhKp2erzCoNrOqKg9IlQwU3z1IDiw=="], 550 | 551 | "selflare/wrangler/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250408.0", "", { "os": "win32", "cpu": "x64" }, "sha512-nJ3RjMKGae2aF2rZ/CNeBvQPM+W5V1SUK0FYWG/uomyr7uQ2l4IayHna1ODg/OHHTEgIjwom0Mbn58iXb0WOcQ=="], 552 | } 553 | } 554 | --------------------------------------------------------------------------------