From 46813965ea3bd08629bb3cdcdc1218a02d95cf5c Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 12:09:55 -0700 Subject: [PATCH 1/7] deps: bump wrangler to 4.100 and workers-types for cf migrate cf migrate needs wrangler/experimental-config (>= 4.100.0). Co-Authored-By: Claude Sonnet 5.5 --- package-lock.json | 127 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8d30e20..536b8f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,19 +15,19 @@ "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20260426.1", + "@cloudflare/workers-types": "^4.20260702.1", "typescript": "5.7.2", - "wrangler": "^4.86.0" + "wrangler": "~4.100.0" } }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", - "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", "dev": true, "license": "MIT OR Apache-2.0", "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, "node_modules/@cloudflare/unenv-preset": { @@ -47,9 +47,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260426.1.tgz", - "integrity": "sha512-Ch7DqsmYzSQRTY87pZpsGsFVz9VVBnLPnCBOHxKt1HH25a7oMu1w1PbPWqVmE0VerCLsj/TScX7Ob3v6E14TZw==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260611.1.tgz", + "integrity": "sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==", "cpu": [ "x64" ], @@ -64,9 +64,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260426.1.tgz", - "integrity": "sha512-0m0U8vaPRH25SpKjbSyRql6gmPe4rCsETRV2WW0qBnuMdKNr5Vh5/Uez80xVrfiCCRMTULGeg63Nqg2vg6CDOA==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260611.1.tgz", + "integrity": "sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==", "cpu": [ "arm64" ], @@ -81,9 +81,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260426.1.tgz", - "integrity": "sha512-C8LlC8uSYzg49y51n++75esxZmMp+Uz1OKHHA/4lkv6rjOTbcHQJuEwSLppjybVIXpv7A8MBhbu9iyCTvyv1mw==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260611.1.tgz", + "integrity": "sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==", "cpu": [ "x64" ], @@ -98,9 +98,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260426.1.tgz", - "integrity": "sha512-ESVp/OIFMAqjQsa8BOP2BQQz5Vpfv6ncN6lNnIuNeOgsISQBdYk+LA60bwQHMud9tvmnSYtONp1zkZ8OQz+x6w==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260611.1.tgz", + "integrity": "sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==", "cpu": [ "arm64" ], @@ -115,9 +115,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260426.1.tgz", - "integrity": "sha512-d3Xj/IjINRgNVwH+eKhpUn4xkkcEewbWXbOvBlapiirKWh5zl9m0Epi3qOqmjyRYK6MICqIGXg4qZBEt0lxudw==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260611.1.tgz", + "integrity": "sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==", "cpu": [ "x64" ], @@ -132,9 +132,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260426.1.tgz", - "integrity": "sha512-cBYeQaWwv/jFV8ualmwp6wIxmAf0rDe2DPPQwPbslKmPHqgv861YpAvm45r05K40QboZgxNQVIPgNkmtHqZeJQ==", + "version": "4.20260702.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260702.1.tgz", + "integrity": "sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA==", "devOptional": true, "license": "MIT OR Apache-2.0" }, @@ -152,9 +152,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", "dev": true, "license": "MIT", "optional": true, @@ -1105,9 +1105,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, @@ -1229,9 +1229,9 @@ } }, "node_modules/@speed-highlight/core": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz", - "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==", + "version": "1.2.24", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.24.tgz", + "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", "dev": true, "license": "CC0-1.0" }, @@ -1461,24 +1461,24 @@ } }, "node_modules/miniflare": { - "version": "4.20260426.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260426.0.tgz", - "integrity": "sha512-KM+v76d04qT+NsPfVKVQEgnnuLNE3uzCCl2QKMTJ5OXor5JbBm1vpkQwQ+l7o5ELCrZ74RnyKhJKLiJyUA39Tw==", + "version": "4.20260611.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260611.0.tgz", + "integrity": "sha512-i+JwEo8vN96naz1WL3ntFgFyRluBDYL408zwhHKvR2jefJ464KsZ/gCmJAQ5k+oaWeb5Ug+s7yne5AyiAEswjg==", "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", - "sharp": "^0.34.5", + "sharp": "0.34.5", "undici": "7.24.8", - "workerd": "1.20260426.1", - "ws": "8.18.0", + "workerd": "1.20260611.1", + "ws": "8.20.1", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" }, "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, "node_modules/pako": { @@ -1549,9 +1549,9 @@ } }, "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -1690,9 +1690,9 @@ } }, "node_modules/workerd": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260426.1.tgz", - "integrity": "sha512-ELvGgN8c9oo+E6EPyecxk1TEf6/eAK4TxxQTW5mQ87C7jbjCzhMbg0P2ije49UBHV0dkBYPJcJvcklUltipl2A==", + "version": "1.20260611.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260611.1.tgz", + "integrity": "sha512-CS/640T7pIJ2HYX6x2DwKFGbcSckAWN3tgcdq+ptB6SaqjWUhlzIgA/YhPuwIU+/NnMnGpqOFX/hC18Oyge63w==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -1703,41 +1703,42 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260426.1", - "@cloudflare/workerd-darwin-arm64": "1.20260426.1", - "@cloudflare/workerd-linux-64": "1.20260426.1", - "@cloudflare/workerd-linux-arm64": "1.20260426.1", - "@cloudflare/workerd-windows-64": "1.20260426.1" + "@cloudflare/workerd-darwin-64": "1.20260611.1", + "@cloudflare/workerd-darwin-arm64": "1.20260611.1", + "@cloudflare/workerd-linux-64": "1.20260611.1", + "@cloudflare/workerd-linux-arm64": "1.20260611.1", + "@cloudflare/workerd-windows-64": "1.20260611.1" } }, "node_modules/wrangler": { - "version": "4.86.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.86.0.tgz", - "integrity": "sha512-9aa/gbF/HiUeeUEwyQpW5LDPBEzyt7iaE6xHwm0vk2Ly8A6J+jh03pzchqVnCCWR832mNyA28MD8oAYt0Kfvlw==", + "version": "4.100.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.100.0.tgz", + "integrity": "sha512-dSQO7DO+mD6XDzkVWIWBoGLO3yw+lacWSc/KhFvd7pgfpth+kX98qb5SGRHZN8ACCDhhfwzDLXwB6qHsIHhfBg==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", - "miniflare": "4.20260426.0", + "miniflare": "4.20260611.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20260426.1" + "workerd": "1.20260611.1" }, "bin": { + "cf-wrangler": "bin/cf-wrangler.js", "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=20.3.0" + "node": ">=22.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "2.3.3" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20260426.1" + "@cloudflare/workers-types": "^4.20260611.1" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -1746,9 +1747,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 5d01850..20637ef 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,8 @@ "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20260426.1", + "@cloudflare/workers-types": "^4.20260702.1", "typescript": "5.7.2", - "wrangler": "^4.86.0" + "wrangler": "~4.100.0" } } From d0b1b0663c040984ca56fedfbf70711c1c4276cf Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 12:18:30 -0700 Subject: [PATCH 2/7] ci: build, preview, and deploy through cf instead of wrangler - cloudflare.config.ts (from cf migrate) + wrangler.config.ts (bundler rules) - dev/deploy npm scripts use cf; deploy workflow uses cf deploy and cf workers versions create (Node 22 for cf) - bump wrangler 4.136, sentry 10.76, workers-types 5.20260929.1 (older 5.x pinned: newest is blocked as recently published) wrangler.toml stays for d1 execute / tail, which cf can't replace yet. Co-Authored-By: Claude Sonnet 5.5 --- .github/workflows/deploy.yml | 38 +- .gitignore | 2 + cloudflare.config.ts | 36 ++ package-lock.json | 1107 ++++++++++++++++++++++++---------- package.json | 11 +- wrangler.config.ts | 13 + 6 files changed, 850 insertions(+), 357 deletions(-) create mode 100644 cloudflare.config.ts create mode 100644 wrangler.config.ts diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index aa3df62..9070521 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "22" cache: "npm" - run: npm ci @@ -41,34 +41,30 @@ jobs: - name: Deploy to production if: github.event_name == 'push' && github.ref == 'refs/heads/main' id: prod - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - command: deploy + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + run: npx cf deploy # ───── PR → versioned preview ────────────────────────────────── - # `versions upload` ships a new version of the existing Worker - # without changing the live deployment. Cloudflare returns a - # unique workers.dev preview URL for that version. The action's - # `deployment-url` output isn't reliably populated for - # `versions upload`, so we parse the URL out of command-output. + # `workers versions create` ships a new version of the existing + # Worker without changing the live deployment. Cloudflare returns + # a unique workers.dev preview URL for that version; we parse it + # out of the command output. - name: Upload preview version if: github.event_name == 'pull_request' id: preview - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - command: versions upload --message "PR #${{ github.event.pull_request.number }} — ${{ github.event.pull_request.head.sha }}" + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + run: | + npx cf workers versions create \ + --message "PR #${{ github.event.pull_request.number }} — ${{ github.event.pull_request.head.sha }}" \ + 2>&1 | tee "$RUNNER_TEMP/cf-preview.log" - - name: Extract preview URL from wrangler output + - name: Extract preview URL from cf output if: github.event_name == 'pull_request' id: extract_url - env: - WRANGLER_STDOUT: ${{ steps.preview.outputs.command-output }} - WRANGLER_STDERR: ${{ steps.preview.outputs.command-stderr }} run: | - combined="$WRANGLER_STDOUT - $WRANGLER_STDERR" + combined=$(cat "$RUNNER_TEMP/cf-preview.log") url=$(printf '%s' "$combined" | grep -oE 'https://[a-z0-9-]+\.[a-z0-9-]+\.workers\.dev' | head -1) if [ -z "$url" ]; then url=$(printf '%s' "$combined" | grep -oE 'https://[a-z0-9-]+\.workers\.dev' | head -1) @@ -84,7 +80,7 @@ jobs: message: | ### 🚀 Cloudflare preview - ${{ steps.extract_url.outputs.url && format('**URL:** {0}', steps.extract_url.outputs.url) || '⚠️ Preview URL not found in wrangler output. Check the **Upload preview version** step logs for the actual URL.' }} + ${{ steps.extract_url.outputs.url && format('**URL:** {0}', steps.extract_url.outputs.url) || '⚠️ Preview URL not found in cf output. Check the **Upload preview version** step logs for the actual URL.' }} Built from commit `${{ github.event.pull_request.head.sha }}`. diff --git a/.gitignore b/.gitignore index 2b9baa2..31a361f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ build/ # --- Cloudflare / Wrangler --- .wrangler/ +.cloudflare/ +worker-configuration.d.ts .dev.vars .dev.vars.* !.dev.vars.example diff --git a/cloudflare.config.ts b/cloudflare.config.ts new file mode 100644 index 0000000..37a23df --- /dev/null +++ b/cloudflare.config.ts @@ -0,0 +1,36 @@ +import { bindings, defineConfig } from "cf/config"; + +// Secrets (GITHUB_CLIENT_SECRET, TOKEN_PEPPER, SENTRY_DSN) are not in this +// file. D1 migrations live in ./migrations (the `cf d1 migrations` default). + +export default defineConfig({ + accountId: "8a9eb8a6efdca98aa450343a55b484cc", + worker: { + name: "htmlbin", + compatibilityDate: "2025-04-01", + compatibilityFlags: [ + "nodejs_compat", + ], + entrypoint: "src/index.ts", + previewUrls: true, + observability: { + enabled: true, + }, + domains: [ + "htmlbin.dev", + "www.htmlbin.dev", + ], + env: { + PUBLIC_URL: bindings.text("https://htmlbin.dev"), + GITHUB_CLIENT_ID: bindings.text("Ov23li6nAqCYrRIN3WSf"), + DB: bindings.d1({ + name: "htmlbin-db", + id: "63632af3-b786-422b-87bd-bf6e13399ec9", + }), + DROPS_KV: bindings.kv({ + id: "915440d1cdfb4876bb3b8c721a694873", + }), + AI: bindings.ai({}), + }, + }, +}); diff --git a/package-lock.json b/package-lock.json index 536b8f8..aabcc5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,32 +9,208 @@ "version": "0.1.0", "dependencies": { "@resvg/resvg-wasm": "^2.6.2", - "@sentry/cloudflare": "^10.53.1", + "@sentry/cloudflare": "^10.76.0", "hono": "^4.13.3", "satori": "^0.26.0", "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20260702.1", + "@cloudflare/workers-types": "5.20260929.1", + "cf": "^1.0.0-beta.12", "typescript": "5.7.2", - "wrangler": "~4.100.0" + "wrangler": "~4.136.0" + } + }, + "node_modules/@cloudflare/build-output-utils": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@cloudflare/build-output-utils/-/build-output-utils-0.8.5.tgz", + "integrity": "sha512-xnwcDCyBSErZeOj5eUy1gTrmVjwIY51TZ0Pz9W7mZqLGA3IkIckud7dNtFdGhKSXL2szfxBRbGM4R4qFE4SoPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cloudflare/config": "0.23.0" + } + }, + "node_modules/@cloudflare/codemods": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/codemods/-/codemods-0.4.0.tgz", + "integrity": "sha512-qeRpKNXtvqhTtagx/5cLmDaFx/voBhWJ1S6SdFdBkE3OtgcPVz+Q8MtIG26zltW9Z0Icsu2FGBxV5RFmuHI/Bg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "cloudflare-codemods": "dist/bin.mjs" + } + }, + "node_modules/@cloudflare/config": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@cloudflare/config/-/config-0.23.0.tgz", + "integrity": "sha512-oE0S7X54esZmJHr9hhCoqODR+yTxxkSYWCLtRiItQdPs0gQuqYw9a13zChhK+8DmdCUJIFBsMAR6t+mfu8g+9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "zod": "4.4.3" } }, "node_modules/@cloudflare/kv-asset-handler": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", - "dev": true, + "devOptional": true, "license": "MIT OR Apache-2.0", "engines": { "node": ">=22.0.0" } }, - "node_modules/@cloudflare/unenv-preset": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz", - "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "node_modules/@cloudflare/runtime-types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@cloudflare/runtime-types/-/runtime-types-0.1.7.tgz", + "integrity": "sha512-avgC1wfTunbVea8HOq4ygiQ0WFQVNxcUHOQvH9TM47+0NTdsVTqB8rPQg6Tb5BfVkcWh/a0RAjk+Elr/h35mtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "miniflare": "5.20261001.0-alpha", + "workerd": "1.20261001.1" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20261001.1.tgz", + "integrity": "sha512-4cgSgDf28JSw/P5Dj5GCS59hzVqS5XnmGAWNkvYHLI6ODU9idGaMMNEuhJXDkEG/lsABmlVlnCgsdh2VbKWepw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20261001.1.tgz", + "integrity": "sha512-8ulAWruEVouNmEIsQsy9WSSCS9zkLu93W2MTwp5esiFyoPp05BNSVFIFsYSPi1pkFmBBd7fsnwMpbLkaJLaVPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20261001.1.tgz", + "integrity": "sha512-kZbTZJGrhsMOdqZ2BIybjaBRLZjYsRLWj7mcNw/6Y3hodOhp5MrNzcz4iWGwNVWwyIV+7Pl+/LX5VcgnRqdHOg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20261001.1.tgz", + "integrity": "sha512-oOk3Zj6k/8oP0FJgZBWDn7+BqbsqIMEMaV95pulHPVbwVu4wYoLfQq2hp0vkbCNsCFLqZb7cqixXdrwD54ZIow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20261001.1.tgz", + "integrity": "sha512-uRxm5W4VyBkoSaoP1BfOuH0873tE+vxsknF4sab6/5YIRvIAufChq3QDp+zlAn67PuGPGcn7W8QraA0t4ucmOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/miniflare": { + "version": "5.20261001.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20261001.0-alpha.tgz", + "integrity": "sha512-GaimS5mSIOMyvd16ga+e1/QkI8cmp3z35QPHFex0DktqNQf2RVZQwMPQXdyoUreUiFP/0Gpe2MoQInTyMAD5xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "0.35.4", + "undici": "7.29.1", + "workerd": "1.20261001.1", + "ws": "8.21.0", + "youch": "4.1.0-beta.10" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/undici": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", + "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/@cloudflare/runtime-types/node_modules/workerd": { + "version": "1.20261001.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20261001.1.tgz", + "integrity": "sha512-d/SIYHFO0PT/wiFZg8in4NpRIxYuFwslX1HdylOtWkBIIUmSpkGFhK820cV84XACFylwJ48xuRoWW/8DWDPsPQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20261001.1", + "@cloudflare/workerd-darwin-arm64": "1.20261001.1", + "@cloudflare/workerd-linux-64": "1.20261001.1", + "@cloudflare/workerd-linux-arm64": "1.20261001.1", + "@cloudflare/workerd-windows-64": "1.20261001.1" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.2.tgz", + "integrity": "sha512-JBP1+Z7ZSNG/d4mRP+y8VC5dka3tZVMLEZRvS+rzQ4DGV1EoxRFQckcJTTkXbHSQiTj0DtNI01Zwb/V2fX0mvQ==", + "devOptional": true, "license": "MIT OR Apache-2.0", "peerDependencies": { "unenv": "2.0.0-rc.24", @@ -47,9 +223,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260611.1.tgz", - "integrity": "sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==", + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260921.1.tgz", + "integrity": "sha512-3iB2WnYOlZ29T+1zhCwbHFExCBp6E9bgmDUMryATYwrIGEQ1YbvR78m4ydm56XKN/d/yF3803ivMGfZMYDtiMg==", "cpu": [ "x64" ], @@ -64,9 +240,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260611.1.tgz", - "integrity": "sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==", + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260921.1.tgz", + "integrity": "sha512-FpqVR7IQXVBmGtajyonEmhmb5UAsmV7dTaIkpemmHZXHEw7uYpkhkzKPjc4BOPhNQy8iwt2p+RZBPMY3Y7/bvQ==", "cpu": [ "arm64" ], @@ -81,9 +257,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260611.1.tgz", - "integrity": "sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==", + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260921.1.tgz", + "integrity": "sha512-riAJIohaVp5A8Sqy4yKlzHOaLPOICMf5oey+jC2rm45RVT+wK8+7UU0d31Dy/02Nc8YUkobAFwNVjX06P8WQ5g==", "cpu": [ "x64" ], @@ -98,9 +274,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260611.1.tgz", - "integrity": "sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==", + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260921.1.tgz", + "integrity": "sha512-tnJu08tT7s0XWDqp3O0H/vCp0voy9OqVAzspb89biMo1dh8IiEpnyXnoPmdJ7H4qBnXCmXgy0kuEphuvpDPj9w==", "cpu": [ "arm64" ], @@ -115,9 +291,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260611.1.tgz", - "integrity": "sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==", + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260921.1.tgz", + "integrity": "sha512-VgNcRPstoZMb1G94JTrx+jU24GtkkazNfox0gnF/2fkuXpcfW/M0e0xvdMovYfwt8ZxG5AB2ZNvanD6ufBwiuQ==", "cpu": [ "x64" ], @@ -132,9 +308,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20260702.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260702.1.tgz", - "integrity": "sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA==", + "version": "5.20260929.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260929.1.tgz", + "integrity": "sha512-VlkFyzSqv2LeMK92eyyfnNvSTW4Nu37cR8T8OM4FF2xcNCsGy8/BxcNk9Jr4ZV0PlmKsCKvS49CfRZTVKBseUw==", "devOptional": true, "license": "MIT OR Apache-2.0" }, @@ -142,7 +318,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" @@ -163,9 +339,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -180,9 +356,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -197,9 +373,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -214,9 +390,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -231,9 +407,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -248,9 +424,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -265,9 +441,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -282,9 +458,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -299,9 +475,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -316,9 +492,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -333,9 +509,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -350,9 +526,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -367,9 +543,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -384,9 +560,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -401,9 +577,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -418,9 +594,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -435,9 +611,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -452,9 +628,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -469,9 +645,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -486,9 +662,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -503,9 +679,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -520,9 +696,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -537,9 +713,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -554,9 +730,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -571,9 +747,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -588,9 +764,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -608,16 +784,16 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", "cpu": [ "arm64" ], @@ -628,19 +804,19 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" + "@img/sharp-libvips-darwin-arm64": "1.3.3" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", "cpu": [ "x64" ], @@ -651,19 +827,56 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" + "@img/sharp-libvips-darwin-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-freebsd-wasm32/node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", "cpu": [ "arm64" ], @@ -678,9 +891,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", "cpu": [ "x64" ], @@ -695,9 +908,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", "cpu": [ "arm" ], @@ -712,9 +925,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", "cpu": [ "arm64" ], @@ -729,9 +942,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", "cpu": [ "ppc64" ], @@ -746,9 +959,9 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", "cpu": [ "riscv64" ], @@ -763,9 +976,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", "cpu": [ "s390x" ], @@ -780,9 +993,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", "cpu": [ "x64" ], @@ -797,9 +1010,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", "cpu": [ "arm64" ], @@ -814,9 +1027,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", "cpu": [ "x64" ], @@ -831,9 +1044,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", "cpu": [ "arm" ], @@ -844,19 +1057,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" + "@img/sharp-libvips-linux-arm": "1.3.3" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", "cpu": [ "arm64" ], @@ -867,19 +1080,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" + "@img/sharp-libvips-linux-arm64": "1.3.3" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", "cpu": [ "ppc64" ], @@ -890,19 +1103,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" + "@img/sharp-libvips-linux-ppc64": "1.3.3" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", "cpu": [ "riscv64" ], @@ -913,19 +1126,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" + "@img/sharp-libvips-linux-riscv64": "1.3.3" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", "cpu": [ "s390x" ], @@ -936,19 +1149,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" + "@img/sharp-libvips-linux-s390x": "1.3.3" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", "cpu": [ "x64" ], @@ -959,19 +1172,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" + "@img/sharp-libvips-linux-x64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", "cpu": [ "arm64" ], @@ -982,19 +1195,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", "cpu": [ "x64" ], @@ -1005,39 +1218,56 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", "cpu": [ "wasm32" ], "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32/node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.7.0" + "@emnapi/runtime": "^1.11.3" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", "cpu": [ "arm64" ], @@ -1048,16 +1278,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", "cpu": [ "ia32" ], @@ -1068,16 +1298,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", "cpu": [ "x64" ], @@ -1088,7 +1318,7 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" @@ -1098,7 +1328,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1108,14 +1338,13 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1135,7 +1364,7 @@ "version": "4.1.6", "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "kleur": "^4.1.5" @@ -1145,7 +1374,7 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@poppinss/colors": "^4.1.5", @@ -1157,7 +1386,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@resvg/resvg-wasm": { @@ -1170,31 +1399,62 @@ } }, "node_modules/@sentry/cloudflare": { - "version": "10.53.1", - "resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.53.1.tgz", - "integrity": "sha512-iSohVibGRAKg7zLUflfA2ePG69Uw6bqm6iCQLM18hoG2gT4DGigaKcjJmZLTfAtW1DInMCb0DYc/mltCznxMrQ==", + "version": "10.76.0", + "resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.76.0.tgz", + "integrity": "sha512-4GdaARNRk17Jd0cvLFfGh+nIXYkCzttBggCf1aJ5Ny5P//nrGz3DSnGRoSZvV8TgZpKbySEi13n+H1NmL5TPbA==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.1", - "@sentry/core": "10.53.1" + "@sentry/core": "10.76.0", + "@sentry/server-utils": "10.76.0", + "magic-string": "~0.30.21" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.x" + "@cloudflare/workers-types": "^4.x || ^5.x", + "wrangler": "^4.x" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { "optional": true + }, + "wrangler": { + "optional": true } } }, + "node_modules/@sentry/conventions": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@sentry/conventions/-/conventions-0.16.0.tgz", + "integrity": "sha512-fO9PLmHdVURcSPUpWCItWAtgKiMwGdJHbovoSEyLplX5sxs2ugvI4CBPTrkkgqhObnZOD0CnWBKDzSVQYBKEyQ==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@sentry/core": { - "version": "10.53.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.53.1.tgz", - "integrity": "sha512-XG4ezlkyuAPjBC5+9kXC94rXXuqYTw9NRhfaDHssbTFaGnqBR8vQX2UUgZfY7ucbeelRDGfBu1sywoU+mB04uA==", + "version": "10.76.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.76.0.tgz", + "integrity": "sha512-H9irBNXHdkgvl86EKlQrPTGYyzvI8GUZ8eoWLay9IuqqZC6pWesf0nH7z/glxKBo7BEw3PIG+unQByHugBnsCg==", "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/server-utils": { + "version": "10.76.0", + "resolved": "https://registry.npmjs.org/@sentry/server-utils/-/server-utils-10.76.0.tgz", + "integrity": "sha512-PJT8i3xsaSEAwVjgVrVClpFVB9+caxn4AVlUbgjt3/NwkoggKmSaoSUq5vpvzFPO11H1V+50qz9xxCw9gc9EzQ==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0", + "@sentry/core": "10.76.0" + }, "engines": { "node": ">=18" } @@ -1219,7 +1479,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -1232,7 +1492,7 @@ "version": "1.2.24", "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.24.tgz", "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", - "dev": true, + "devOptional": true, "license": "CC0-1.0" }, "node_modules/base64-js": { @@ -1248,7 +1508,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/camelize": { @@ -1260,6 +1520,163 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/cf": { + "version": "1.0.0-beta.12", + "resolved": "https://registry.npmjs.org/cf/-/cf-1.0.0-beta.12.tgz", + "integrity": "sha512-tyQ+Jpnw+4NDwDtl7ZNteXBm7N0TeJ6gYww79kkabpcYoCEXkUUpmt9BlDUKH8ub17tjAeiuyqa9NQzH0vp2Aw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/build-output-utils": "0.8.5", + "@cloudflare/codemods": "0.4.0", + "@cloudflare/config": "0.23.0", + "@cloudflare/runtime-types": "0.1.7", + "blake3-wasm": "2.1.5", + "miniflare": "5.20260930.0-alpha", + "minisearch": "7.2.0" + }, + "bin": { + "cf": "bin/cf", + "cloudflare": "bin/cf" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/cf/node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260930.2.tgz", + "integrity": "sha512-wxKsfekWeev6xkjHEMx3x7nz6WfWOn1/scQ8geqWQhUm8qRl1ZRZhjnj+rucIMLhLhP9RGSYMZIjEm3AV0zwVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/cf/node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260930.2.tgz", + "integrity": "sha512-cviPpheZGQ2H5X+Ctxd3wfxhksNrdyoNprjSgg3br2+psetKacjdEvK8CILdN/2GF+u1KOExvr45amSL6lgzGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/cf/node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260930.2.tgz", + "integrity": "sha512-cwrJAC5y/avPd1OzGyhc5OvUUfPXBFc065TY5CjXp7Hb3dhiTx6JeB5Pc8L3G8L8M44HyAfRHSpoLtRr+SR3cQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/cf/node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260930.2.tgz", + "integrity": "sha512-FHucB4gak1IuT+IxLx3KbtMBMapZhcqD9EdhHvBxk1FpHwD2QU5x26MRRVN53jIKG/O25HUmE9yffb3cMANQgw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/cf/node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260930.2.tgz", + "integrity": "sha512-JHFMdGFMqP+M2QiVzZq1S8Ie66Gvxo7Og5EYz/KtmDvGCqge5L3lK+ksZxAhF3j/tpSLqdvlUvcTKoR9PkwTTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/cf/node_modules/miniflare": { + "version": "5.20260930.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260930.0-alpha.tgz", + "integrity": "sha512-vZljfRtOEeynbhJtuvYsnCU8t6zF5wIUm9ql4YFHB7zvYw2+F2tpT0BzXjzaa++eiUIml1gsODCf02qShBmJdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "0.35.4", + "undici": "7.29.1", + "workerd": "1.20260930.2", + "ws": "8.21.0", + "youch": "4.1.0-beta.10" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/cf/node_modules/undici": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", + "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/cf/node_modules/workerd": { + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260930.2.tgz", + "integrity": "sha512-k1lQzEiGyCDqaRsR5+o9PBT5wVU5omtas6hXx3spbEHHMFo8a7tkAixVCMsWFeiT7xhrmg21Hd6a9jLNrkcUMg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260930.2", + "@cloudflare/workerd-darwin-arm64": "1.20260930.2", + "@cloudflare/workerd-linux-64": "1.20260930.2", + "@cloudflare/workerd-linux-arm64": "1.20260930.2", + "@cloudflare/workerd-windows-64": "1.20260930.2" + } + }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", @@ -1270,7 +1687,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -1325,7 +1742,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -1344,17 +1761,17 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -1364,32 +1781,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/escape-html": { @@ -1444,7 +1861,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" @@ -1460,27 +1877,40 @@ "unicode-trie": "^2.0.0" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/miniflare": { - "version": "4.20260611.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260611.0.tgz", - "integrity": "sha512-i+JwEo8vN96naz1WL3ntFgFyRluBDYL408zwhHKvR2jefJ464KsZ/gCmJAQ5k+oaWeb5Ug+s7yne5AyiAEswjg==", - "dev": true, + "version": "5.20260921.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260921.0-alpha.tgz", + "integrity": "sha512-vHH/unOYvV2jA1Q9SdkmzrQhhMoksdwg5jegu6ZeKaaRzgxZhVbt1NdTpQjHF2VTgiBjgP8SiUlUMfruB3N3SQ==", + "devOptional": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", - "sharp": "0.34.5", - "undici": "7.24.8", - "workerd": "1.20260611.1", - "ws": "8.20.1", + "sharp": "0.35.4", + "undici": "7.29.0", + "workerd": "1.20260921.1", + "ws": "8.21.0", "youch": "4.1.0-beta.10" }, - "bin": { - "miniflare": "bootstrap.js" - }, "engines": { "node": ">=22.0.0" } }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -1501,14 +1931,14 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/postcss-value-parser": { @@ -1552,7 +1982,7 @@ "version": "7.8.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -1562,48 +1992,53 @@ } }, "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "dev": true, - "hasInstallScript": true, + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@img/colour": "^1.0.0", + "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", - "semver": "^7.7.3" + "semver": "^7.8.5" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/string.prototype.codepointat": { @@ -1616,7 +2051,7 @@ "version": "10.2.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -1660,10 +2095,10 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.8.tgz", - "integrity": "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ==", - "dev": true, + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=20.18.1" @@ -1673,7 +2108,7 @@ "version": "2.0.0-rc.24", "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "pathe": "^2.0.3" @@ -1690,10 +2125,10 @@ } }, "node_modules/workerd": { - "version": "1.20260611.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260611.1.tgz", - "integrity": "sha512-CS/640T7pIJ2HYX6x2DwKFGbcSckAWN3tgcdq+ptB6SaqjWUhlzIgA/YhPuwIU+/NnMnGpqOFX/hC18Oyge63w==", - "dev": true, + "version": "1.20260921.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260921.1.tgz", + "integrity": "sha512-4HyG7G1W4ksa6tUZ8bV2jxDRWuL5PXnHm9+Z1sjFPb9OZNoYtXz4y7QQRh4ibi0BF/lOmlAVjbhkUqsAVZuUKA==", + "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "bin": { @@ -1703,28 +2138,28 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260611.1", - "@cloudflare/workerd-darwin-arm64": "1.20260611.1", - "@cloudflare/workerd-linux-64": "1.20260611.1", - "@cloudflare/workerd-linux-arm64": "1.20260611.1", - "@cloudflare/workerd-windows-64": "1.20260611.1" + "@cloudflare/workerd-darwin-64": "1.20260921.1", + "@cloudflare/workerd-darwin-arm64": "1.20260921.1", + "@cloudflare/workerd-linux-64": "1.20260921.1", + "@cloudflare/workerd-linux-arm64": "1.20260921.1", + "@cloudflare/workerd-windows-64": "1.20260921.1" } }, "node_modules/wrangler": { - "version": "4.100.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.100.0.tgz", - "integrity": "sha512-dSQO7DO+mD6XDzkVWIWBoGLO3yw+lacWSc/KhFvd7pgfpth+kX98qb5SGRHZN8ACCDhhfwzDLXwB6qHsIHhfBg==", - "dev": true, + "version": "4.136.3", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.136.3.tgz", + "integrity": "sha512-L1bS8BI9xoEk3RRr5XoZn5q5k1jCRo8+37ZEEab/jsUFzE1Ea2sIBAbmP1CdwSeD6mZYmnUtR6xpi9esHIl6GA==", + "devOptional": true, "license": "MIT OR Apache-2.0", "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", - "@cloudflare/unenv-preset": "2.16.1", + "@cloudflare/unenv-preset": "2.16.2", "blake3-wasm": "2.1.5", - "esbuild": "0.27.3", - "miniflare": "4.20260611.0", + "esbuild": "0.28.1", + "miniflare": "5.20260921.0-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20260611.1" + "workerd": "1.20260921.1" }, "bin": { "cf-wrangler": "bin/cf-wrangler.js", @@ -1738,7 +2173,7 @@ "fsevents": "2.3.3" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20260611.1" + "@cloudflare/workers-types": "^5.20260921.1" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -1747,10 +2182,10 @@ } }, "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "dev": true, + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -1778,7 +2213,7 @@ "version": "4.1.0-beta.10", "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@poppinss/colors": "^4.1.5", @@ -1792,12 +2227,22 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 20637ef..24758d5 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "description": "Agent-first HTML hosting. Drop HTML, get a URL. htmlbin.dev", "type": "module", "scripts": { - "dev": "node node_modules/wrangler/bin/wrangler.js dev", - "deploy": "node node_modules/wrangler/bin/wrangler.js deploy", + "dev": "cf dev", + "deploy": "cf deploy", "tail": "node node_modules/wrangler/bin/wrangler.js tail", "db:apply:local": "node node_modules/wrangler/bin/wrangler.js d1 execute htmlbin-db --local --file=./schema.sql", "db:apply:remote": "node node_modules/wrangler/bin/wrangler.js d1 execute htmlbin-db --remote --file=./schema.sql", @@ -22,14 +22,15 @@ }, "dependencies": { "@resvg/resvg-wasm": "^2.6.2", - "@sentry/cloudflare": "^10.53.1", + "@sentry/cloudflare": "^10.76.0", "hono": "^4.13.3", "satori": "^0.26.0", "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20260702.1", + "@cloudflare/workers-types": "5.20260929.1", + "cf": "^1.0.0-beta.12", "typescript": "5.7.2", - "wrangler": "~4.100.0" + "wrangler": "~4.136.0" } } diff --git a/wrangler.config.ts b/wrangler.config.ts new file mode 100644 index 0000000..6e7c3b3 --- /dev/null +++ b/wrangler.config.ts @@ -0,0 +1,13 @@ +import { defineWranglerConfig } from "wrangler/experimental-config"; + +export default defineWranglerConfig({ + rules: [ + { + type: "CompiledWasm", + globs: [ + "**/*.wasm", + ], + fallthrough: true, + }, + ], +}); From 591961b15c4bc8fc070a60e6c8a41080851d451f Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 12:30:01 -0700 Subject: [PATCH 3/7] docs: document the cf CLI migration, gaps, and gotchas Co-Authored-By: Claude Sonnet 5.5 --- AGENTS.md | 6 +++--- CLAUDE.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++------- README.md | 2 +- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 20780f1..40671ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,7 +41,7 @@ reference-only and must not ship in the public version. 5. Do not introduce a new format keyword or relitigate the old HTMD naming. Product is `htmlbin`; artifacts are "drops". 6. Keep the aesthetic aligned with `DESIGN.md`. -7. Never deploy production directly. No local `wrangler deploy`. No +7. Never deploy production directly. No local `cf deploy` or `wrangler deploy`. No `git push origin main`. Ship through branch -> PR -> preview URL -> user approval -> merge to `main`. @@ -87,7 +87,7 @@ The only production path is `.github/workflows/deploy.yml`: 5. Test the preview URL and wait for explicit user approval. 6. Merge to `main`; the workflow deploys production. -Do not bypass this with local Wrangler deploys or direct pushes. +Do not bypass this with local `cf`/Wrangler deploys or direct pushes. ## API Conventions @@ -184,7 +184,7 @@ src/views/ landing, verify, viewer, favicon, OG views skills/htmlbin/SKILL.md human-browsable mirror of src/skill.ts schema.sql D1 schema migrations/ D1 migrations -wrangler.toml Cloudflare config +cloudflare.config.ts Cloudflare config read by cf (wrangler.toml kept for wrangler-only commands) scripts/setup.mjs provisioning scripts/agent-e2e.sh full functional test scripts/stats.mjs text-based stats snapshot (npm run stats) diff --git a/CLAUDE.md b/CLAUDE.md index 1bd6a8c..bf15ece 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,16 +66,16 @@ them ships something the user will reject: English, not a coined term we own. We do not have authority to define a new format spec, so don't act like we do. 6. **Aesthetic stays in DESIGN.md.** Don't drift. -7. **Never deploy to production directly.** No `wrangler deploy` from - the local shell. No `git push origin main`. Every change ships +7. **Never deploy to production directly.** No `cf deploy` / + `wrangler deploy` from the local shell. No `git push origin main`. Every change ships through this exact flow: 1. Create a new branch (`git checkout -b `). 2. Commit and `git push -u origin `. - 3. Open a PR. GitHub Actions runs `wrangler versions upload` and + 3. Open a PR. GitHub Actions runs `cf workers versions create` and posts a Cloudflare preview URL as a sticky comment on the PR. 4. Test against that preview URL. Wait for the user's approval. 5. After the user approves, merge the PR. The merge-to-`main` - workflow runs `wrangler deploy` for production — that is the + workflow runs `cf deploy` for production — that is the only path code reaches `htmlbin.dev`. Even for a one-line copy fix. No exceptions. @@ -619,6 +619,48 @@ WASM gotchas (don't relitigate): the SVG is the lightweight fallback + per-tab rendering source; the PNG is what social platforms actually consume. +## CLI: `cf` (beta) with Wrangler as fallback + +Build, preview and deploy go through Cloudflare's `cf` CLI (npm `cf`, +open beta since Sept 2026, Node >= 22.18; CI uses Node 22). Wrangler is +still a devDependency because `cf` delegates bundling to it and because +`cf` can't yet replace a few commands. + +- **Config.** `cloudflare.config.ts` (from `cf migrate`) is what `cf` + reads. `wrangler.config.ts` only carries bundler options (the + CompiledWasm `rules`). `wrangler.toml` is **kept** for the Wrangler-only + commands below, so bindings live in two places: change both. +- **On `cf`:** `npm run dev` (`cf dev`), `npm run deploy` (`cf deploy`), + PR previews (`cf workers versions create`), prod deploy in CI. +- **Still on Wrangler:** `tail` (no live-log equivalent found), + `db:*` scripts, `scripts/stats.mjs` and the dashboard. `cf d1 query` + ignores `--local` and always calls the remote API, `cf` has no local + `execute --file`, and Wrangler's d1 commands resolve `htmlbin-db` + from `wrangler.toml`. +- **`cf` equivalents found:** `cf workers secrets update + --worker htmlbin --text …` (secrets), `cf d1 migrations apply|list + ` (takes the UUID, same `d1_migrations` table as Wrangler), + `cf previews deploy` (named previews, untested here). +- **Two logins.** `cf dev` runs the AI binding remotely through its + bundled Wrangler, which uses its own auth. Run `cf auth login` *and* + `wrangler login` (or set `CLOUDFLARE_API_TOKEN`), otherwise `cf dev` + dies with `Failed to fetch auth token` / `[object Object]`. +- **Local state.** `cf dev` defaults to `~/.config/cloudflare/state`. + Use `cf dev --persist-to .wrangler/state` to reuse the DB that + `npm run db:apply:local` seeds. +- **Version pins.** `cf` needs Wrangler >= 4.136. `@cloudflare/workers-types` + is pinned to an exact 5.x release that is a week old because the Socket + firewall blocks packages published the same day; Sentry >= 10.76 is + needed for the workers-types 5 peer range. +- **Gitignored output:** `.cloudflare/` (build output) and + `worker-configuration.d.ts` (regenerated by `cf dev`). +- **`cf` help output** includes an "AGENTS: use `cf cli search`" banner; + that is a real discovery command and the quickest way to find a + command (`cf cli search ""`). +- `npm run typecheck` fails locally with `Cannot find module + '../lib/tsc.js'` (same broken-shim cause as the Wrangler gotcha below); + run `node node_modules/typescript/bin/tsc --noEmit`. CI is unaffected. + ## Bundling non-JS assets in the Worker — the wrangler gotcha **`wrangler 4 + ES module Workers does not reliably honor `[[rules]]` @@ -695,15 +737,15 @@ Spec: https://developers.cloudflare.com/workers/static-assets/ ## CI / continuous deploy — the *only* deploy path `.github/workflows/deploy.yml` is the **single way** code reaches -production. Hard rule #7 above: never `wrangler deploy` locally and +production. Hard rule #7 above: never `cf deploy` / `wrangler deploy` locally and never push directly to `main`. Both bypass review. The workflow: -- **PR opened or pushed to** — type-check, `wrangler versions upload`, +- **PR opened or pushed to** — type-check, `cf workers versions create`, post the Cloudflare preview URL as a sticky comment on the PR (`https://-htmlbin..workers.dev`). -- **Merge to `main`** — type-check, `wrangler deploy` to production. +- **Merge to `main`** — type-check, `cf deploy` to production. Triggered by the merge, never by a human running wrangler. Mandatory loop for every change: diff --git a/README.md b/README.md index 702ec21..483f747 100644 --- a/README.md +++ b/README.md @@ -250,7 +250,7 @@ skills/htmlbin/ .github/workflows/ deploy.yml ─ production deploy on main, versioned preview on PR schema.sql ─ D1 schema -wrangler.toml ─ Cloudflare config (incl. [[rules]] CompiledWasm for OG fonts) +cloudflare.config.ts ─ Cloudflare config for the cf CLI (wrangler.toml kept for tail/d1; wrangler.config.ts holds the CompiledWasm rule) scripts/ setup.mjs ─ one-shot provisioning agent-e2e.sh ─ full functional test From fc820a861dc5ea76deacb4a1d180d7a2ace047a1 Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 12:36:50 -0700 Subject: [PATCH 4/7] deps: wrangler 4.145 / workers-types 5.20260930.2 to clear undici advisory wrangler 4.136's miniflare pulled undici 7.29.0 (high severity), which fails the npm audit gate via @sentry/cloudflare's wrangler peer. Co-Authored-By: Claude Sonnet 5.5 --- package-lock.json | 228 +++++++++------------------------------------- package.json | 4 +- 2 files changed, 44 insertions(+), 188 deletions(-) diff --git a/package-lock.json b/package-lock.json index aabcc5e..e6b1d44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,10 @@ "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "5.20260929.1", + "@cloudflare/workers-types": "5.20260930.2", "cf": "^1.0.0-beta.12", "typescript": "5.7.2", - "wrangler": "~4.136.0" + "wrangler": "4.145.0" } }, "node_modules/@cloudflare/build-output-utils": { @@ -175,16 +175,6 @@ "node": ">=22.0.0" } }, - "node_modules/@cloudflare/runtime-types/node_modules/undici": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", - "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, "node_modules/@cloudflare/runtime-types/node_modules/workerd": { "version": "1.20261001.1", "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20261001.1.tgz", @@ -223,9 +213,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260921.1.tgz", - "integrity": "sha512-3iB2WnYOlZ29T+1zhCwbHFExCBp6E9bgmDUMryATYwrIGEQ1YbvR78m4ydm56XKN/d/yF3803ivMGfZMYDtiMg==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260930.2.tgz", + "integrity": "sha512-wxKsfekWeev6xkjHEMx3x7nz6WfWOn1/scQ8geqWQhUm8qRl1ZRZhjnj+rucIMLhLhP9RGSYMZIjEm3AV0zwVQ==", "cpu": [ "x64" ], @@ -240,9 +230,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260921.1.tgz", - "integrity": "sha512-FpqVR7IQXVBmGtajyonEmhmb5UAsmV7dTaIkpemmHZXHEw7uYpkhkzKPjc4BOPhNQy8iwt2p+RZBPMY3Y7/bvQ==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260930.2.tgz", + "integrity": "sha512-cviPpheZGQ2H5X+Ctxd3wfxhksNrdyoNprjSgg3br2+psetKacjdEvK8CILdN/2GF+u1KOExvr45amSL6lgzGA==", "cpu": [ "arm64" ], @@ -257,9 +247,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260921.1.tgz", - "integrity": "sha512-riAJIohaVp5A8Sqy4yKlzHOaLPOICMf5oey+jC2rm45RVT+wK8+7UU0d31Dy/02Nc8YUkobAFwNVjX06P8WQ5g==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260930.2.tgz", + "integrity": "sha512-cwrJAC5y/avPd1OzGyhc5OvUUfPXBFc065TY5CjXp7Hb3dhiTx6JeB5Pc8L3G8L8M44HyAfRHSpoLtRr+SR3cQ==", "cpu": [ "x64" ], @@ -274,9 +264,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260921.1.tgz", - "integrity": "sha512-tnJu08tT7s0XWDqp3O0H/vCp0voy9OqVAzspb89biMo1dh8IiEpnyXnoPmdJ7H4qBnXCmXgy0kuEphuvpDPj9w==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260930.2.tgz", + "integrity": "sha512-FHucB4gak1IuT+IxLx3KbtMBMapZhcqD9EdhHvBxk1FpHwD2QU5x26MRRVN53jIKG/O25HUmE9yffb3cMANQgw==", "cpu": [ "arm64" ], @@ -291,9 +281,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260921.1.tgz", - "integrity": "sha512-VgNcRPstoZMb1G94JTrx+jU24GtkkazNfox0gnF/2fkuXpcfW/M0e0xvdMovYfwt8ZxG5AB2ZNvanD6ufBwiuQ==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260930.2.tgz", + "integrity": "sha512-JHFMdGFMqP+M2QiVzZq1S8Ie66Gvxo7Og5EYz/KtmDvGCqge5L3lK+ksZxAhF3j/tpSLqdvlUvcTKoR9PkwTTQ==", "cpu": [ "x64" ], @@ -308,9 +298,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "5.20260929.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260929.1.tgz", - "integrity": "sha512-VlkFyzSqv2LeMK92eyyfnNvSTW4Nu37cR8T8OM4FF2xcNCsGy8/BxcNk9Jr4ZV0PlmKsCKvS49CfRZTVKBseUw==", + "version": "5.20260930.2", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260930.2.tgz", + "integrity": "sha512-zOJM3vdCVB7iszFDvXvusORu1Ssre6+6x1t+opmbJ4ahi4keylnK/hB6/dKuRPLG7eqS/DO7W4IMjvas6pCvJg==", "devOptional": true, "license": "MIT OR Apache-2.0" }, @@ -1543,140 +1533,6 @@ "node": ">=22" } }, - "node_modules/cf/node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260930.2.tgz", - "integrity": "sha512-wxKsfekWeev6xkjHEMx3x7nz6WfWOn1/scQ8geqWQhUm8qRl1ZRZhjnj+rucIMLhLhP9RGSYMZIjEm3AV0zwVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/cf/node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260930.2.tgz", - "integrity": "sha512-cviPpheZGQ2H5X+Ctxd3wfxhksNrdyoNprjSgg3br2+psetKacjdEvK8CILdN/2GF+u1KOExvr45amSL6lgzGA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/cf/node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260930.2.tgz", - "integrity": "sha512-cwrJAC5y/avPd1OzGyhc5OvUUfPXBFc065TY5CjXp7Hb3dhiTx6JeB5Pc8L3G8L8M44HyAfRHSpoLtRr+SR3cQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/cf/node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260930.2.tgz", - "integrity": "sha512-FHucB4gak1IuT+IxLx3KbtMBMapZhcqD9EdhHvBxk1FpHwD2QU5x26MRRVN53jIKG/O25HUmE9yffb3cMANQgw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/cf/node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260930.2.tgz", - "integrity": "sha512-JHFMdGFMqP+M2QiVzZq1S8Ie66Gvxo7Og5EYz/KtmDvGCqge5L3lK+ksZxAhF3j/tpSLqdvlUvcTKoR9PkwTTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/cf/node_modules/miniflare": { - "version": "5.20260930.0-alpha", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260930.0-alpha.tgz", - "integrity": "sha512-vZljfRtOEeynbhJtuvYsnCU8t6zF5wIUm9ql4YFHB7zvYw2+F2tpT0BzXjzaa++eiUIml1gsODCf02qShBmJdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "0.8.1", - "sharp": "0.35.4", - "undici": "7.29.1", - "workerd": "1.20260930.2", - "ws": "8.21.0", - "youch": "4.1.0-beta.10" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/cf/node_modules/undici": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", - "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/cf/node_modules/workerd": { - "version": "1.20260930.2", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260930.2.tgz", - "integrity": "sha512-k1lQzEiGyCDqaRsR5+o9PBT5wVU5omtas6hXx3spbEHHMFo8a7tkAixVCMsWFeiT7xhrmg21Hd6a9jLNrkcUMg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "bin": { - "workerd": "bin/workerd" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260930.2", - "@cloudflare/workerd-darwin-arm64": "1.20260930.2", - "@cloudflare/workerd-linux-64": "1.20260930.2", - "@cloudflare/workerd-linux-arm64": "1.20260930.2", - "@cloudflare/workerd-windows-64": "1.20260930.2" - } - }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", @@ -1887,16 +1743,16 @@ } }, "node_modules/miniflare": { - "version": "5.20260921.0-alpha", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260921.0-alpha.tgz", - "integrity": "sha512-vHH/unOYvV2jA1Q9SdkmzrQhhMoksdwg5jegu6ZeKaaRzgxZhVbt1NdTpQjHF2VTgiBjgP8SiUlUMfruB3N3SQ==", + "version": "5.20260930.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260930.0-alpha.tgz", + "integrity": "sha512-vZljfRtOEeynbhJtuvYsnCU8t6zF5wIUm9ql4YFHB7zvYw2+F2tpT0BzXjzaa++eiUIml1gsODCf02qShBmJdg==", "devOptional": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.4", - "undici": "7.29.0", - "workerd": "1.20260921.1", + "undici": "7.29.1", + "workerd": "1.20260930.2", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, @@ -2095,9 +1951,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", - "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.1.tgz", + "integrity": "sha512-RYONW2MeafgYlkVOKYKkA/Ag7BmXqgIWCa8t1m0JcxrQg9pI9lEqRhAOruOBCbAohOa/gkCF+iPi9hrgvTzu6Q==", "devOptional": true, "license": "MIT", "engines": { @@ -2125,9 +1981,9 @@ } }, "node_modules/workerd": { - "version": "1.20260921.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260921.1.tgz", - "integrity": "sha512-4HyG7G1W4ksa6tUZ8bV2jxDRWuL5PXnHm9+Z1sjFPb9OZNoYtXz4y7QQRh4ibi0BF/lOmlAVjbhkUqsAVZuUKA==", + "version": "1.20260930.2", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260930.2.tgz", + "integrity": "sha512-k1lQzEiGyCDqaRsR5+o9PBT5wVU5omtas6hXx3spbEHHMFo8a7tkAixVCMsWFeiT7xhrmg21Hd6a9jLNrkcUMg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -2138,17 +1994,17 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260921.1", - "@cloudflare/workerd-darwin-arm64": "1.20260921.1", - "@cloudflare/workerd-linux-64": "1.20260921.1", - "@cloudflare/workerd-linux-arm64": "1.20260921.1", - "@cloudflare/workerd-windows-64": "1.20260921.1" + "@cloudflare/workerd-darwin-64": "1.20260930.2", + "@cloudflare/workerd-darwin-arm64": "1.20260930.2", + "@cloudflare/workerd-linux-64": "1.20260930.2", + "@cloudflare/workerd-linux-arm64": "1.20260930.2", + "@cloudflare/workerd-windows-64": "1.20260930.2" } }, "node_modules/wrangler": { - "version": "4.136.3", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.136.3.tgz", - "integrity": "sha512-L1bS8BI9xoEk3RRr5XoZn5q5k1jCRo8+37ZEEab/jsUFzE1Ea2sIBAbmP1CdwSeD6mZYmnUtR6xpi9esHIl6GA==", + "version": "4.145.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.145.0.tgz", + "integrity": "sha512-TdO9l7RNqM2Kb5/AynhlRPF9WPhaI0W4Gcpq2FkyU1iZ+xPW25sfV8Yc48PsI1GsNEFOfdh2RTOIpW8U22AqHw==", "devOptional": true, "license": "MIT OR Apache-2.0", "dependencies": { @@ -2156,10 +2012,10 @@ "@cloudflare/unenv-preset": "2.16.2", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", - "miniflare": "5.20260921.0-alpha", + "miniflare": "5.20260930.0-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20260921.1" + "workerd": "1.20260930.2" }, "bin": { "cf-wrangler": "bin/cf-wrangler.js", @@ -2173,7 +2029,7 @@ "fsevents": "2.3.3" }, "peerDependencies": { - "@cloudflare/workers-types": "^5.20260921.1" + "@cloudflare/workers-types": "^5.20260930.2" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { diff --git a/package.json b/package.json index 24758d5..1133ef8 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,9 @@ "satori-html": "^0.3.2" }, "devDependencies": { - "@cloudflare/workers-types": "5.20260929.1", + "@cloudflare/workers-types": "5.20260930.2", "cf": "^1.0.0-beta.12", "typescript": "5.7.2", - "wrangler": "~4.136.0" + "wrangler": "4.145.0" } } From b7ff53a68e6eaef9f60f3706bc941c0bcb932c69 Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 12:59:34 -0700 Subject: [PATCH 5/7] docs: correct cf d1 --local behaviour and version pins Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index bf15ece..2fbfe14 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -634,7 +634,8 @@ still a devDependency because `cf` delegates bundling to it and because PR previews (`cf workers versions create`), prod deploy in CI. - **Still on Wrangler:** `tail` (no live-log equivalent found), `db:*` scripts, `scripts/stats.mjs` and the dashboard. `cf d1 query` - ignores `--local` and always calls the remote API, `cf` has no local + has no local equivalent (with `--local` it errors; with `--local + --dry-run` it still prints the remote request), `cf` has no local `execute --file`, and Wrangler's d1 commands resolve `htmlbin-db` from `wrangler.toml`. - **`cf` equivalents found:** `cf workers secrets update @@ -648,10 +649,12 @@ still a devDependency because `cf` delegates bundling to it and because - **Local state.** `cf dev` defaults to `~/.config/cloudflare/state`. Use `cf dev --persist-to .wrangler/state` to reuse the DB that `npm run db:apply:local` seeds. -- **Version pins.** `cf` needs Wrangler >= 4.136. `@cloudflare/workers-types` - is pinned to an exact 5.x release that is a week old because the Socket - firewall blocks packages published the same day; Sentry >= 10.76 is - needed for the workers-types 5 peer range. +- **Version pins.** `cf` needs Wrangler >= 4.136; we use 4.145 because + 4.136 and 4.140 pull `undici@7.29.0` (high-severity advisory), which fails + the CI `npm audit` gate through `@sentry/cloudflare`'s wrangler peer. + `@cloudflare/workers-types` is pinned to an exact 5.x release a few days + old because the Socket firewall blocks packages published the same day; + Sentry >= 10.76 is needed for the workers-types 5 peer range. - **Gitignored output:** `.cloudflare/` (build output) and `worker-configuration.d.ts` (regenerated by `cf dev`). - **`cf` help output** includes an "AGENTS: use `cf cli search`" banner; From 41596201f6bb7876bca986379fa6d7961e4c7902 Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 13:50:28 -0700 Subject: [PATCH 6/7] fix: pipefail on preview upload, npm run dev uses the seeded local DB - tee hid a failed cf upload (default Actions bash has no pipefail) - cf dev defaults to ~/.config/cloudflare/state; point it at .wrangler/state - refresh stale wrangler mentions in .dev.vars.example Co-Authored-By: Claude Opus 5.5 --- .dev.vars.example | 4 ++-- .github/workflows/deploy.yml | 2 ++ AGENTS.md | 2 +- CLAUDE.md | 8 +++++--- package.json | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.dev.vars.example b/.dev.vars.example index 2540c67..8852079 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -1,7 +1,7 @@ # Copy to .dev.vars (gitignored) for local development. -# These override [vars] in wrangler.toml when running `wrangler dev`. +# These override [vars] in cloudflare.config.ts when running `cf dev`. -# Local dev overrides — production uses the values in wrangler.toml. +# Local dev overrides — production uses the values in cloudflare.config.ts. PUBLIC_URL="http://localhost:8787" # Random 32+ char string. Generate with: openssl rand -hex 32 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9070521..99eed06 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,7 +55,9 @@ jobs: id: preview env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + # pipefail so a failed upload fails the step instead of tee's exit 0. run: | + set -o pipefail npx cf workers versions create \ --message "PR #${{ github.event.pull_request.number }} — ${{ github.event.pull_request.head.sha }}" \ 2>&1 | tee "$RUNNER_TEMP/cf-preview.log" diff --git a/AGENTS.md b/AGENTS.md index 40671ea..a6b2b49 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -184,7 +184,7 @@ src/views/ landing, verify, viewer, favicon, OG views skills/htmlbin/SKILL.md human-browsable mirror of src/skill.ts schema.sql D1 schema migrations/ D1 migrations -cloudflare.config.ts Cloudflare config read by cf (wrangler.toml kept for wrangler-only commands) +cloudflare.config.ts Cloudflare config read by cf (wrangler.toml kept for wrangler-only commands) scripts/setup.mjs provisioning scripts/agent-e2e.sh full functional test scripts/stats.mjs text-based stats snapshot (npm run stats) diff --git a/CLAUDE.md b/CLAUDE.md index 2fbfe14..480d02c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -641,14 +641,16 @@ still a devDependency because `cf` delegates bundling to it and because - **`cf` equivalents found:** `cf workers secrets update --worker htmlbin --text …` (secrets), `cf d1 migrations apply|list ` (takes the UUID, same `d1_migrations` table as Wrangler), - `cf previews deploy` (named previews, untested here). + `cf previews deploy` (named previews; untested, and its source has a + "Preview uploads from Build Output don't support the `domains` field" + error, which our config may trip). - **Two logins.** `cf dev` runs the AI binding remotely through its bundled Wrangler, which uses its own auth. Run `cf auth login` *and* `wrangler login` (or set `CLOUDFLARE_API_TOKEN`), otherwise `cf dev` dies with `Failed to fetch auth token` / `[object Object]`. - **Local state.** `cf dev` defaults to `~/.config/cloudflare/state`. - Use `cf dev --persist-to .wrangler/state` to reuse the DB that - `npm run db:apply:local` seeds. + `npm run dev` passes `--persist-to .wrangler/state` so it reuses the DB + that `npm run db:apply:local` seeds. - **Version pins.** `cf` needs Wrangler >= 4.136; we use 4.145 because 4.136 and 4.140 pull `undici@7.29.0` (high-severity advisory), which fails the CI `npm audit` gate through `@sentry/cloudflare`'s wrangler peer. diff --git a/package.json b/package.json index 1133ef8..ce0631f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Agent-first HTML hosting. Drop HTML, get a URL. htmlbin.dev", "type": "module", "scripts": { - "dev": "cf dev", + "dev": "cf dev --persist-to .wrangler/state", "deploy": "cf deploy", "tail": "node node_modules/wrangler/bin/wrangler.js tail", "db:apply:local": "node node_modules/wrangler/bin/wrangler.js d1 execute htmlbin-db --local --file=./schema.sql", From cdf3407b6b06e86b8e4b623b87c773d0452c496d Mon Sep 17 00:00:00 2001 From: Utkarsh Sengar Date: Mon, 5 Oct 2026 14:00:31 -0700 Subject: [PATCH 7/7] Run every command through cf; delete wrangler.toml - db:* scripts use cf d1 raw / cf d1 migrations (by database UUID) - stats.mjs and the dashboard query through cf d1 raw - setup.mjs provisions D1/KV and secrets with cf - drop the tail script (no cf equivalent; use cf observability telemetry query) - local cf d1 commands use .wrangler/state, the dir cf dev always writes - docs: command map, the --sql= gotcha, why wrangler stays a dependency Co-Authored-By: Claude Opus 5.5 --- .dev.vars.example | 2 +- .gitignore | 2 +- AGENTS.md | 4 +- CLAUDE.md | 158 +++++++++++++++++++---------------- DESIGN.md | 2 +- README.md | 18 ++-- package.json | 15 ++-- scripts/dashboard/index.html | 2 +- scripts/dashboard/server.mjs | 36 ++++---- scripts/setup.mjs | 45 +++++----- scripts/stats.mjs | 24 +++--- wrangler.toml | 71 ---------------- 12 files changed, 158 insertions(+), 221 deletions(-) delete mode 100644 wrangler.toml diff --git a/.dev.vars.example b/.dev.vars.example index 8852079..23d207d 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -18,5 +18,5 @@ GITHUB_CLIENT_SECRET="dev-mock" # Sentry observability. Optional in dev. When unset, both the Worker # wrapper and the browser /sentry.js route no-op. DSN is public — Sentry # expects it in client code. Set in production via: -# wrangler secret put SENTRY_DSN +# cf workers secrets update SENTRY_DSN --worker htmlbin --type secret_text --text # SENTRY_DSN="https://@oXXXXX.ingest.sentry.io/" diff --git a/.gitignore b/.gitignore index 31a361f..c01c4bb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ build/ .parcel-cache/ *.tsbuildinfo -# --- Cloudflare / Wrangler --- +# --- Cloudflare --- .wrangler/ .cloudflare/ worker-configuration.d.ts diff --git a/AGENTS.md b/AGENTS.md index a6b2b49..806a9ef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -157,7 +157,7 @@ callback with a synthesized identity. ## Asset Gotchas -Wrangler 4 + ES module Workers has been unreliable for importing +The bundler (Wrangler 4, which cf builds with) has been unreliable for importing non-JS files outside `src/` through `[[rules]]`. Use established patterns: @@ -184,7 +184,7 @@ src/views/ landing, verify, viewer, favicon, OG views skills/htmlbin/SKILL.md human-browsable mirror of src/skill.ts schema.sql D1 schema migrations/ D1 migrations -cloudflare.config.ts Cloudflare config read by cf (wrangler.toml kept for wrangler-only commands) +cloudflare.config.ts Cloudflare config read by cf (all commands go through cf) scripts/setup.mjs provisioning scripts/agent-e2e.sh full functional test scripts/stats.mjs text-based stats snapshot (npm run stats) diff --git a/CLAUDE.md b/CLAUDE.md index 480d02c..f414ea0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -174,8 +174,8 @@ single-use secret. The callback re-checks `verifications.status` after GitHub returns, in case the row expired during the round-trip. **Bindings:** `GITHUB_CLIENT_ID` is a public `[vars]` entry in -`wrangler.toml`. `GITHUB_CLIENT_SECRET` is a Worker secret -(`wrangler secret put GITHUB_CLIENT_SECRET`). The OAuth app's +`cloudflare.config.ts`. `GITHUB_CLIENT_SECRET` is a Worker secret +(`cf workers secrets update GITHUB_CLIENT_SECRET --worker htmlbin --type secret_text --text …`). The OAuth app's "Authorization callback URL" must be `https://htmlbin.dev/auth/github/callback`. **Dev mock:** when `GITHUB_CLIENT_ID === "dev-mock"` (the value in @@ -441,7 +441,7 @@ The landing page is also available as Markdown via Workers AI: - `GET /?format=md` — querystring fallback Result is cached in KV (`md:landing`, 1h). Requires Workers AI binding -(`[ai]` block in wrangler.toml — already set up). See +(`AI: bindings.ai({})` in cloudflare.config.ts — already set up). See https://blog.cloudflare.com/markdown-for-agents/ for the underlying API. User-uploaded drops at `/p/:id` are **not** auto-converted — agents @@ -598,7 +598,7 @@ Slack, Twitter, iMessage, and most unfurlers don't render SVG OG cards WASM gotchas (don't relitigate): - Workers block `WebAssembly.compile`. We use `satori/standalone` and call `init(yogaWasmModule)` with a precompiled `WebAssembly.Module` - imported via wrangler's `[[rules]] type = "CompiledWasm"` glob. Same + imported via the `CompiledWasm` rule in `wrangler.config.ts`. Same trick for `@resvg/resvg-wasm/index_bg.wasm`. - `satori-html` was removed because it doesn't decode HTML entities (the `` wordmark rendered literally as `<htmlbin>`). @@ -619,52 +619,73 @@ WASM gotchas (don't relitigate): the SVG is the lightweight fallback + per-tab rendering source; the PNG is what social platforms actually consume. -## CLI: `cf` (beta) with Wrangler as fallback - -Build, preview and deploy go through Cloudflare's `cf` CLI (npm `cf`, -open beta since Sept 2026, Node >= 22.18; CI uses Node 22). Wrangler is -still a devDependency because `cf` delegates bundling to it and because -`cf` can't yet replace a few commands. - -- **Config.** `cloudflare.config.ts` (from `cf migrate`) is what `cf` - reads. `wrangler.config.ts` only carries bundler options (the - CompiledWasm `rules`). `wrangler.toml` is **kept** for the Wrangler-only - commands below, so bindings live in two places: change both. -- **On `cf`:** `npm run dev` (`cf dev`), `npm run deploy` (`cf deploy`), - PR previews (`cf workers versions create`), prod deploy in CI. -- **Still on Wrangler:** `tail` (no live-log equivalent found), - `db:*` scripts, `scripts/stats.mjs` and the dashboard. `cf d1 query` - has no local equivalent (with `--local` it errors; with `--local - --dry-run` it still prints the remote request), `cf` has no local - `execute --file`, and Wrangler's d1 commands resolve `htmlbin-db` - from `wrangler.toml`. -- **`cf` equivalents found:** `cf workers secrets update - --worker htmlbin --text …` (secrets), `cf d1 migrations apply|list - ` (takes the UUID, same `d1_migrations` table as Wrangler), - `cf previews deploy` (named previews; untested, and its source has a - "Preview uploads from Build Output don't support the `domains` field" - error, which our config may trip). -- **Two logins.** `cf dev` runs the AI binding remotely through its - bundled Wrangler, which uses its own auth. Run `cf auth login` *and* - `wrangler login` (or set `CLOUDFLARE_API_TOKEN`), otherwise `cf dev` - dies with `Failed to fetch auth token` / `[object Object]`. -- **Local state.** `cf dev` defaults to `~/.config/cloudflare/state`. - `npm run dev` passes `--persist-to .wrangler/state` so it reuses the DB - that `npm run db:apply:local` seeds. +## CLI: `cf` (beta) — every command runs through it + +Every npm script, CI step and doc command uses Cloudflare's `cf` CLI +(npm `cf`, open beta since Sept 2026, Node >= 22.18; CI uses Node 22). +There is no `wrangler.toml` and no script calls Wrangler. + +**Wrangler is still an npm dependency, and has to be.** `cf` builds by +delegating to Wrangler (`cf deploy` prints "Delegating to Wrangler" and +refuses to run below Wrangler 4.136), and `cf dev` runs its local server +and remote bindings through it. `@cloudflare/vite-plugin` depends on +Wrangler too, so switching bundlers doesn't remove it. Treat it as a +build dependency of `cf`, not a CLI we use. + +- **Config.** `cloudflare.config.ts` (from `cf migrate`) holds the Worker, + bindings, vars and domains. `wrangler.config.ts` only carries bundler + options (the CompiledWasm `rules` for the OG renderer) — that's where + `cf` expects them. +- **Command map.** + + | Task | Command | + |---|---| + | local dev | `npm run dev` → `cf dev` | + | PR preview (CI) | `cf workers versions create --message …` | + | prod deploy (CI only) | `cf deploy` | + | seed local DB | `npm run db:apply:local` → `cf d1 raw --local …` | + | migrations | `npm run db:migrate:*` → `cf d1 migrations apply\|list ` | + | stats / dashboard | `cf d1 raw` (rows come back as arrays; the scripts zip them into objects) | + | secrets | `cf workers secrets update --worker htmlbin --type secret_text --text …` | + | logs | `cf observability telemetry query` (queries recent logs; there is no live `tail`) | + +- **D1 commands take the database UUID**, not the name + (`63632af3-b786-422b-87bd-bf6e13399ec9`). `cf d1 migrations` uses the same + `d1_migrations` table Wrangler did, so applied history carries over. +- **`cf d1 raw` runs locally; `cf d1 query` doesn't** (with `--local` it + errors "no local equivalent"). Use `raw` for anything local. +- **Pass SQL as `--sql=…`, not `--sql …`.** `schema.sql` starts with `--`, + which the CLI parser otherwise reads as a flag. +- **Local state is `.wrangler/state`, and that's fixed.** `cf dev` ignores + `--persist-to` (both as its own flag and forwarded after `--`); its + bundled Wrangler always writes the Worker's local D1/KV there. So every + local `cf d1` command passes `--persist-to .wrangler/state` to hit the + same database. The directory name is the only Wrangler-named thing left. +- **Two logins for `cf dev`.** The AI binding runs remotely through the + bundled Wrangler, which keeps its own auth. Run `cf auth login` *and* + `npm exec -- wrangler login` once (or set `CLOUDFLARE_API_TOKEN`); + otherwise `cf dev` dies with `Failed to fetch auth token` / + `[object Object]`. - **Version pins.** `cf` needs Wrangler >= 4.136; we use 4.145 because 4.136 and 4.140 pull `undici@7.29.0` (high-severity advisory), which fails the CI `npm audit` gate through `@sentry/cloudflare`'s wrangler peer. `@cloudflare/workers-types` is pinned to an exact 5.x release a few days old because the Socket firewall blocks packages published the same day; Sentry >= 10.76 is needed for the workers-types 5 peer range. +- **Deploys keep secrets.** `cf deploy` and `cf workers versions create` + both send `keep_bindings` for secrets (checked in the `cf` source), so + `TOKEN_PEPPER` etc. survive a deploy, as with Wrangler. +- **`cf previews deploy`** exists but is untested; its source has a + "Preview uploads from Build Output don't support the `domains` field" + error, which our config may trip. CI uses `workers versions create`. - **Gitignored output:** `.cloudflare/` (build output) and `worker-configuration.d.ts` (regenerated by `cf dev`). - **`cf` help output** includes an "AGENTS: use `cf cli search`" banner; that is a real discovery command and the quickest way to find a command (`cf cli search ""`). -- `npm run typecheck` fails locally with `Cannot find module - '../lib/tsc.js'` (same broken-shim cause as the Wrangler gotcha below); - run `node node_modules/typescript/bin/tsc --noEmit`. CI is unaffected. +- `npm run typecheck` can fail locally with `Cannot find module + '../lib/tsc.js'` (a broken `.bin` shim); run + `node node_modules/typescript/bin/tsc --noEmit`. CI is unaffected. ## Bundling non-JS assets in the Worker — the wrangler gotcha @@ -720,7 +741,7 @@ When we do migrate (good follow-up, especially if we ever want to serve more static files), the steps: 1. `mv assets/fonts public/fonts` -2. Add `[assets] directory = "./public"` to `wrangler.toml` +2. Add the static-assets directory to `cloudflare.config.ts` 3. Delete `src/fonts.ts` and `src/fonts-data.ts` 4. Remove the `/fonts/:name` route + `FONTS` import in `src/index.ts` 5. Move `FONT_FACE_CSS` into `src/styles.ts` as an inline string @@ -751,7 +772,7 @@ The workflow: post the Cloudflare preview URL as a sticky comment on the PR (`https://-htmlbin..workers.dev`). - **Merge to `main`** — type-check, `cf deploy` to production. - Triggered by the merge, never by a human running wrangler. + Triggered by the merge, never by a human running `cf deploy`. Mandatory loop for every change: @@ -766,15 +787,15 @@ Mandatory loop for every change: Concurrency cancels superseded PR runs but never cancels a mid-flight `main` deploy. The only secret in GitHub is `CLOUDFLARE_API_TOKEN` (template "Edit Cloudflare Workers"). Worker secrets (`TOKEN_PEPPER`, -`GITHUB_CLIENT_SECRET`) are managed via `wrangler secret put` against +`GITHUB_CLIENT_SECRET`) are managed via `cf workers secrets update` against production; preview versions share the same bindings because they live on the same Worker. ## Local operator dashboard (`npm run dashboard`) — not a product surface `scripts/dashboard/server.mjs` is a tiny Node HTTP server that binds to -`127.0.0.1:5173` and proxies read-only SQL through `wrangler d1 execute ---remote --json` (same pattern as `stats.mjs`). The static SPA in +`127.0.0.1:5173` and proxies read-only SQL through `cf d1 raw` +(same pattern as `stats.mjs`). The static SPA in `scripts/dashboard/{index.html,app.js,style.css}` renders an interactive overview with click-through into any user (drops, tokens, signup date, daily activity) and any drop (versions, owner, storage). User detail @@ -799,17 +820,11 @@ yourself wanting that, stop and ask the user first. - Read-only. The server has no SQL mutation path. Inputs are strict whitelists (`user_id` matches `/^[A-Za-z0-9_-]{1,64}$/`, `slug` matches `/^[A-Za-z0-9]{6,12}$/`, window is a fixed enum) before SQL - interpolation because `wrangler d1 execute --command` doesn't accept - bind params. + interpolation because `cf d1 raw --sql` doesn't accept bind params. - 30s in-memory query cache so click-around doesn't re-hit remote D1. -- **Wrangler invocation:** the server runs - `node node_modules/wrangler/bin/wrangler.js` directly, *not* `npx - wrangler`. The `.bin/wrangler` shim is installed as a regular file - (not a symlink), so its `__dirname`-relative path math resolves - `node_modules/wrangler-dist/cli.js` (wrong) instead of - `node_modules/wrangler/wrangler-dist/cli.js`. `stats.mjs` still uses - `npx wrangler`; if that breaks the same way, copy the direct-invoke - pattern from the dashboard. +- **`cf` invocation:** both the server and `stats.mjs` run + `node_modules/.bin/cf d1 raw --sql=…` and zip the returned + `columns` + `rows` arrays into objects. - Vanilla HTML/JS/CSS, no build step, no new npm dependencies. SVG bar charts hand-rolled. - Routes are hash-based: `#/` overview, `#/u/` user detail, @@ -824,25 +839,15 @@ yourself wanting that, stop and ask the user first. callback with `?mock_login=`. The deterministic mock id derives from SHA-256 of the login. Production uses real OAuth app credentials from `github.com/settings/applications/new`. -- **D1** in local mode is in `.wrangler/state/`. Run - `npm run db:apply:local` after schema changes. For column-only +- **D1** in local mode is in `.wrangler/state/` (where `cf dev` keeps it). + Run `npm run db:apply:local` after schema changes. For column-only changes against an existing DB, write a new file in `migrations/` and run `npm run db:migrate:local` / `:remote`. The migration scripts - call `wrangler d1 migrations apply` under the hood, which tracks + call `cf d1 migrations apply` under the hood, which tracks applied migrations in a `d1_migrations` table — drop a new `migrations/-.sql` and it gets picked up automatically; no npm-script edit needed. `npm run db:migrate:list:local` / `:remote` shows what's pending. -- **Wrangler invocation in npm scripts.** All `db:*` scripts call - `node node_modules/wrangler/bin/wrangler.js …` directly rather than - bare `wrangler`. Why: the `.bin/wrangler` shim is installed as a - regular file (not a symlink), so its `__dirname`-relative path math - resolves `node_modules/wrangler-dist/cli.js` (wrong) instead of - `node_modules/wrangler/wrangler-dist/cli.js`. Same gotcha the - dashboard server hit — see `scripts/dashboard/server.mjs`. The - `dev`/`deploy`/`tail` scripts kept the bare form because they happen - to work; if they ever break the same way, copy the direct-invoke - pattern. - **Token prefix is `hb_`.** If you change it, update both `src/auth.ts` (regex) AND `src/crypto.ts:newApiToken` AND `src/index.ts` (existing-token validation regex). @@ -856,7 +861,7 @@ yourself wanting that, stop and ask the user first. `htmlbin.dev/api/*` without a `User-Agent` header are rejected by Cloudflare with `403` + error `1010` before they reach the Worker. The CLI, any direct `curl`/`fetch`, and the e2e script must send a UA - (we use `htmlbin-cli/`). Local `wrangler dev` doesn't sit + (we use `htmlbin-cli/`). Local `cf dev` doesn't sit behind that ruleset so it only bites against `htmlbin.dev` itself. ## Observability (Sentry) @@ -903,10 +908,14 @@ URLs work without any DSN. templates as `text/plain`; non-HTML responses aren't rewritten. Keep it that way. The e2e asserts the served bytes, not just the content type. - **Config:** `SENTRY_DSN` is a Worker secret. Because this Worker - uses versioned deploys (CI runs `wrangler versions upload` on PRs), - use `wrangler versions secret put SENTRY_DSN` — *not* the plain - `wrangler secret put`, which errors with "latest version of your - Worker isn't currently deployed." Local dev: copy `.dev.vars.example` + uses versioned deploys (CI runs `cf workers versions create` on PRs), + the plain secrets endpoint errored under Wrangler with "latest version + of your Worker isn't currently deployed" (`wrangler secret put`), and + `cf workers secrets update` calls that same endpoint. If it errors, + attach the secret to a version instead with `cf workers versions create + --secrets-file ` (untested; Wrangler's answer was `versions secret + put`). Never `cf deploy` from the shell to do this — hard rule #7. + Local dev: copy `.dev.vars.example` and uncomment the `SENTRY_DSN` line. The DSN is *public* by Sentry's design — embedding it in client JS is intended. - **CLI:** `sentry-cli` is for source-map upload + release tagging. @@ -957,13 +966,14 @@ patterns/ ─ human-browsable canonical pattern markdown — source of schema.sql ─ D1 schema (idempotent for fresh installs) migrations/ ─ ALTER-style migrations against an existing D1 -wrangler.toml ─ Cloudflare config (Worker name, D1, KV, AI, [[rules]] CompiledWasm) +cloudflare.config.ts ─ Cloudflare config read by cf (Worker name, D1, KV, AI, domains) +wrangler.config.ts ─ bundler options cf hands to its builder ([[rules]] CompiledWasm) scripts/ setup.mjs ─ provisions D1 + KV, applies schema, sets pepper agent-e2e.sh ─ full functional test stats.mjs ─ text-based stats snapshot (npm run stats) dashboard/ ─ local-only operator web UI (npm run dashboard) - server.mjs ─ http server + wrangler subprocess proxy + server.mjs ─ http server + `cf d1 raw` subprocess proxy index.html / app.js / style.css ─ vanilla SPA, no build step .dev.vars.example ─ TOKEN_PEPPER + GITHUB_CLIENT_ID/SECRET (dev-mock) ``` diff --git a/DESIGN.md b/DESIGN.md index 0619fbf..79b5bfe 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -614,7 +614,7 @@ because of its full-bleed iframe — that's the kind of override we accept). To restyle the whole product: 1. Edit `src/styles.ts` -2. Save — wrangler hot-reloads, hash bumps automatically +2. Save — `cf dev` hot-reloads, hash bumps automatically > **Gotcha: `STYLES_CSS` is a TypeScript template literal.** A backtick > anywhere inside it — including inside a CSS comment — terminates the diff --git a/README.md b/README.md index 483f747..a5c23c9 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ npm run dashboard -- --local # against local D1 ``` A tiny Node + vanilla-JS dashboard that proxies read-only SQL through -`wrangler d1 execute` and renders an interactive overview with +`cf d1 raw` and renders an interactive overview with click-through into any user (drops, tokens, signup date, daily activity) or any drop (versions, owner, storage). User detail pulls real name / bio / followers / repos from the public GitHub API. Sibling of @@ -86,8 +86,8 @@ deployed, not part of the product surface. # 1. Real GitHub OAuth app # https://github.com/settings/applications/new # - Authorization callback URL: https://htmlbin.dev/auth/github/callback -# Paste the client id into wrangler.toml; the secret is a Worker secret: -wrangler secret put GITHUB_CLIENT_SECRET +# Paste the client id into cloudflare.config.ts; the secret is a Worker secret: +cf workers secrets update GITHUB_CLIENT_SECRET --worker htmlbin --type secret_text --text # 2. Apply schema (fresh DB) or migrations (existing DB) to remote npm run db:apply:remote # fresh DB only @@ -97,8 +97,8 @@ npm run db:migrate:remote # existing DB — applies migrations/ npm run deploy ``` -Custom domain: in the Cloudflare dashboard, attach `htmlbin.dev` to the -Worker, then uncomment the `routes` block in `wrangler.toml`. +Custom domain: list it under `worker.domains` in `cloudflare.config.ts`; +the next deploy attaches it. ### Continuous deploy (GitHub Actions) @@ -117,9 +117,8 @@ That's it. PRs automatically get a Cloudflare preview URL commented back; merges to `main` deploy to production. > Bindings (D1, KV, AI) are shared between previews and production. -> Add an `[env.preview]` block in `wrangler.toml` with separate IDs if -> you want isolated preview data — see -> . +> For isolated preview data, give previews their own D1/KV IDs (cf +> evaluates `cloudflare.config.ts` per `--mode`). ## API @@ -250,7 +249,8 @@ skills/htmlbin/ .github/workflows/ deploy.yml ─ production deploy on main, versioned preview on PR schema.sql ─ D1 schema -cloudflare.config.ts ─ Cloudflare config for the cf CLI (wrangler.toml kept for tail/d1; wrangler.config.ts holds the CompiledWasm rule) +cloudflare.config.ts ─ Cloudflare config for the cf CLI +wrangler.config.ts ─ bundler options cf passes to its builder (CompiledWasm rule) scripts/ setup.mjs ─ one-shot provisioning agent-e2e.sh ─ full functional test diff --git a/package.json b/package.json index ce0631f..b5c8eed 100644 --- a/package.json +++ b/package.json @@ -5,15 +5,14 @@ "description": "Agent-first HTML hosting. Drop HTML, get a URL. htmlbin.dev", "type": "module", "scripts": { - "dev": "cf dev --persist-to .wrangler/state", + "dev": "cf dev", "deploy": "cf deploy", - "tail": "node node_modules/wrangler/bin/wrangler.js tail", - "db:apply:local": "node node_modules/wrangler/bin/wrangler.js d1 execute htmlbin-db --local --file=./schema.sql", - "db:apply:remote": "node node_modules/wrangler/bin/wrangler.js d1 execute htmlbin-db --remote --file=./schema.sql", - "db:migrate:local": "node node_modules/wrangler/bin/wrangler.js d1 migrations apply htmlbin-db --local", - "db:migrate:remote": "node node_modules/wrangler/bin/wrangler.js d1 migrations apply htmlbin-db --remote", - "db:migrate:list:local": "node node_modules/wrangler/bin/wrangler.js d1 migrations list htmlbin-db --local", - "db:migrate:list:remote": "node node_modules/wrangler/bin/wrangler.js d1 migrations list htmlbin-db --remote", + "db:apply:local": "cf d1 raw 63632af3-b786-422b-87bd-bf6e13399ec9 --local --persist-to .wrangler/state \"--sql=$(cat schema.sql)\"", + "db:apply:remote": "cf d1 raw 63632af3-b786-422b-87bd-bf6e13399ec9 \"--sql=$(cat schema.sql)\"", + "db:migrate:local": "cf d1 migrations apply 63632af3-b786-422b-87bd-bf6e13399ec9 --local --persist-to .wrangler/state", + "db:migrate:remote": "cf d1 migrations apply 63632af3-b786-422b-87bd-bf6e13399ec9", + "db:migrate:list:local": "cf d1 migrations list 63632af3-b786-422b-87bd-bf6e13399ec9 --local --persist-to .wrangler/state", + "db:migrate:list:remote": "cf d1 migrations list 63632af3-b786-422b-87bd-bf6e13399ec9", "setup": "node scripts/setup.mjs", "stats": "node scripts/stats.mjs", "dashboard": "node scripts/dashboard/server.mjs", diff --git a/scripts/dashboard/index.html b/scripts/dashboard/index.html index 8daea21..2e57168 100644 --- a/scripts/dashboard/index.html +++ b/scripts/dashboard/index.html @@ -13,7 +13,7 @@
loading…
-
local-only · queries via wrangler d1 execute
+
local-only · queries via cf d1 raw
diff --git a/scripts/dashboard/server.mjs b/scripts/dashboard/server.mjs index cd3c724..5ca394f 100644 --- a/scripts/dashboard/server.mjs +++ b/scripts/dashboard/server.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env node // Local visual dashboard for htmlbin. // -// Spawns `wrangler d1 execute --remote --json` for queries (same pattern as +// Spawns `cf d1 raw` for queries (same pattern as // scripts/stats.mjs) and serves a small SPA at http://127.0.0.1:5173 with // overview + per-user + per-drop drill-down views. // @@ -20,15 +20,14 @@ import { fileURLToPath } from "node:url"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, "..", ".."); const PORT = Number(process.env.PORT) || 5173; -const ENV_FLAG = process.argv.includes("--local") ? "--local" : "--remote"; -const ENV_LABEL = ENV_FLAG === "--local" ? "local" : "remote"; - -// Invoke wrangler's entry point directly. `npx wrangler` works in -// theory but the `.bin/wrangler` shim is installed as a regular file -// (not a symlink) which breaks its `__dirname`-based path math. -const WRANGLER_ENTRY = resolve(REPO_ROOT, "node_modules", "wrangler", "bin", "wrangler.js"); -if (!existsSync(WRANGLER_ENTRY)) { - console.error(`wrangler not found at ${WRANGLER_ENTRY} — run \`npm install\` first.`); +const LOCAL = process.argv.includes("--local"); +const ENV_ARGS = LOCAL ? ["--local", "--persist-to", ".wrangler/state"] : []; +const ENV_LABEL = LOCAL ? "local" : "remote"; +const DB_ID = "63632af3-b786-422b-87bd-bf6e13399ec9"; + +const CF_BIN = resolve(REPO_ROOT, "node_modules", ".bin", "cf"); +if (!existsSync(CF_BIN)) { + console.error(`cf not found at ${CF_BIN} — run \`npm install\` first.`); process.exit(1); } @@ -42,29 +41,28 @@ function runQuery(sql) { let out; try { out = execFileSync( - process.execPath, - [ - WRANGLER_ENTRY, "d1", "execute", "htmlbin-db", - ENV_FLAG, "--json", "--command", flat, - ], + CF_BIN, + ["d1", "raw", DB_ID, ...ENV_ARGS, `--sql=${flat}`], { stdio: ["ignore", "pipe", "pipe"], cwd: REPO_ROOT }, ).toString(); } catch (e) { const msg = e.stderr?.toString() || e.message || "unknown"; - throw new Error(`wrangler failed: ${msg.slice(0, 800)}`); + throw new Error(`cf failed: ${msg.slice(0, 800)}`); } const match = out.match(/\[\s*\{/); if (!match) { if (out.match(/\[\s*\]/)) return []; - throw new Error(`unexpected wrangler output:\n${out.slice(0, 400)}`); + throw new Error(`unexpected cf output:\n${out.slice(0, 400)}`); } - const results = JSON.parse(out.slice(match.index))[0]?.results ?? []; + // `cf d1 raw` returns rows as arrays; zip them back into objects. + const { columns = [], rows = [] } = JSON.parse(out.slice(match.index))[0]?.results ?? {}; + const results = rows.map((row) => Object.fromEntries(columns.map((c, i) => [c, row[i]]))); cache.set(flat, { results, expires: Date.now() + CACHE_TTL_MS }); return results; } // ── inputs ───────────────────────────────────────────────────────── -// Strict whitelists. wrangler d1 execute --command does not accept bind +// Strict whitelists. `cf d1 raw --sql` does not accept bind // params, so every interpolated value comes through one of these gates. const RE_USER = /^[A-Za-z0-9_-]{1,64}$/; const RE_SLUG = /^[A-Za-z0-9]{6,12}$/; diff --git a/scripts/setup.mjs b/scripts/setup.mjs index 024abe1..41722ab 100755 --- a/scripts/setup.mjs +++ b/scripts/setup.mjs @@ -1,12 +1,12 @@ #!/usr/bin/env node -// One-shot setup: provision Cloudflare D1 + KV, patch wrangler.toml, +// One-shot setup: provision Cloudflare D1 + KV, patch cloudflare.config.ts, // apply schema, and prompt for the secrets we need. // // Usage: npm run setup // -// Requires: wrangler logged in (`wrangler login`), Node 18+. +// Requires: cf logged in (`cf auth login`), Node 22.18+. -import { execSync } from "node:child_process"; +import { execSync, execFileSync } from "node:child_process"; import { readFileSync, writeFileSync } from "node:fs"; import { randomBytes } from "node:crypto"; import path from "node:path"; @@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(__dirname, ".."); -const wranglerPath = path.join(root, "wrangler.toml"); +const configPath = path.join(root, "cloudflare.config.ts"); function sh(cmd) { return execSync(cmd, { stdio: ["inherit", "pipe", "inherit"] }).toString(); @@ -32,37 +32,36 @@ function patch(file, find, replace) { console.log("→ Creating D1 database 'htmlbin-db' …"); let d1Out; try { - d1Out = sh(`npx wrangler d1 create htmlbin-db`); + d1Out = sh(`npx cf d1 create --name htmlbin-db`); } catch { console.log(" (already exists, fetching id from `d1 list`)"); - d1Out = sh(`npx wrangler d1 list --json`); + d1Out = sh(`npx cf d1 list --name htmlbin-db`); } -const d1Match = d1Out.match(/"uuid":\s*"([a-f0-9-]+)"|database_id\s*=\s*"([a-f0-9-]+)"/); -const d1Id = d1Match?.[1] ?? d1Match?.[2]; +const d1Id = d1Out.match(/"uuid":\s*"([a-f0-9-]+)"/)?.[1]; if (!d1Id) { - console.error("Couldn't extract D1 id. Set it manually in wrangler.toml."); + console.error("Couldn't extract D1 id. Set it manually in cloudflare.config.ts."); process.exit(1); } console.log(` D1 id: ${d1Id}`); console.log("→ Creating KV namespace 'DROPS_KV' …"); -const kvOut = sh(`npx wrangler kv namespace create DROPS_KV`); -const kvMatch = kvOut.match(/id\s*=\s*"([a-f0-9]+)"/); -const kvId = kvMatch?.[1]; +const kvOut = sh(`npx cf kv namespaces create --title DROPS_KV`); +const kvId = kvOut.match(/"id":\s*"([a-f0-9]{32})"/)?.[1]; if (!kvId) { - console.error("Couldn't extract KV id. Set it manually in wrangler.toml."); + console.error("Couldn't extract KV id. Set it manually in cloudflare.config.ts."); process.exit(1); } console.log(` KV id: ${kvId}`); -console.log("→ Patching wrangler.toml …"); -patch(wranglerPath, /REPLACE_WITH_D1_ID/g, d1Id); -patch(wranglerPath, /REPLACE_WITH_KV_ID/g, kvId); +console.log("→ Patching cloudflare.config.ts …"); +patch(configPath, /REPLACE_WITH_D1_ID/g, d1Id); +patch(configPath, /REPLACE_WITH_KV_ID/g, kvId); console.log("→ Applying schema (local + remote) …"); -sh(`npx wrangler d1 execute htmlbin-db --local --file=./schema.sql`); +const schema = readFileSync(path.join(root, "schema.sql"), "utf8"); +execFileSync("npx", ["cf", "d1", "raw", d1Id, "--local", "--persist-to", ".wrangler/state", `--sql=${schema}`], { stdio: ["inherit", "pipe", "inherit"] }); try { - sh(`npx wrangler d1 execute htmlbin-db --remote --file=./schema.sql`); + execFileSync("npx", ["cf", "d1", "raw", d1Id, `--sql=${schema}`], { stdio: ["inherit", "pipe", "inherit"] }); } catch (e) { console.warn(" (remote apply failed — run `npm run db:apply:remote` after deploy)"); } @@ -70,11 +69,11 @@ try { console.log("→ Setting TOKEN_PEPPER secret …"); const pepper = randomBytes(32).toString("hex"); try { - execSync(`echo "${pepper}" | npx wrangler secret put TOKEN_PEPPER`, { - stdio: "inherit", + execFileSync("npx", ["cf", "workers", "secrets", "update", "TOKEN_PEPPER", "--worker", "htmlbin", "--type", "secret_text", "--text", pepper], { + stdio: ["inherit", "pipe", "inherit"], }); } catch (e) { - console.warn(" (couldn't set secret — set manually with `wrangler secret put TOKEN_PEPPER`)"); + console.warn(" (couldn't set secret — the Worker must exist first; deploy, then run `cf workers secrets update TOKEN_PEPPER --worker htmlbin --type secret_text --text `)"); } console.log(""); @@ -85,8 +84,8 @@ console.log(" 1. Register a GitHub OAuth app at"); console.log(" https://github.com/settings/applications/new"); console.log(" - Authorization callback URL:"); console.log(" https:///auth/github/callback"); -console.log(" Paste the Client ID into wrangler.toml as GITHUB_CLIENT_ID,"); -console.log(" then run: wrangler secret put GITHUB_CLIENT_SECRET"); +console.log(" Paste the Client ID into cloudflare.config.ts as GITHUB_CLIENT_ID,"); +console.log(" then run: cf workers secrets update GITHUB_CLIENT_SECRET --worker htmlbin --type secret_text --text "); console.log(""); console.log(" 2. For local dev, copy .dev.vars.example to .dev.vars. The"); console.log(" defaults use a 'dev-mock' sentinel that short-circuits"); diff --git a/scripts/stats.mjs b/scripts/stats.mjs index a0e4787..e3d1d2a 100755 --- a/scripts/stats.mjs +++ b/scripts/stats.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env node // Local stats + risk-signal CLI for htmlbin. // -// Runs SQL via `wrangler d1 execute` and prints a single screenful: +// Runs SQL via `cf d1 raw` and prints a single screenful: // adoption snapshot, time-series (day/week/month buckets), top // drops/users, and risk signals that surface only when something's // off (burst writes, zero-view aging, rate-limit hits, etc.). @@ -10,7 +10,7 @@ // npm run stats # day buckets, last 14 days, remote // npm run stats -- --window=week # weekly buckets, last 12 weeks // npm run stats -- --window=month --buckets=6 -// npm run stats -- --local # query local .wrangler/state/ D1 +// npm run stats -- --local # query local .wrangler/state/ D1 (where cf dev keeps it) import { execFileSync } from "node:child_process"; import { parseArgs } from "node:util"; @@ -39,7 +39,8 @@ if (!Number.isFinite(BUCKETS) || BUCKETS < 1) { console.error(`--buckets must be a positive integer`); process.exit(1); } -const ENV_FLAG = values.local ? "--local" : "--remote"; +const DB_ID = "63632af3-b786-422b-87bd-bf6e13399ec9"; +const ENV_ARGS = values.local ? ["--local", "--persist-to", ".wrangler/state"] : []; const ENV_LABEL = values.local ? "local" : "remote"; // ── time helpers ─────────────────────────────────────────────────── @@ -114,14 +115,14 @@ function bucketCutoffMs(w, count) { return NOW - count * unit; } -// ── wrangler helper ──────────────────────────────────────────────── +// ── cf helper ────────────────────────────────────────────────────── function runQuery(sql) { const flat = sql.replace(/\s+/g, " ").trim(); let out; try { out = execFileSync( - process.execPath, - ["node_modules/wrangler/bin/wrangler.js", "d1", "execute", "htmlbin-db", ENV_FLAG, "--json", "--command", flat], + "node_modules/.bin/cf", + ["d1", "raw", DB_ID, ...ENV_ARGS, `--sql=${flat}`], { stdio: ["ignore", "pipe", "pipe"] }, ).toString(); } catch (e) { @@ -131,17 +132,18 @@ function runQuery(sql) { if (e.stderr?.length) console.error(` stderr:\n${e.stderr.toString()}`); process.exit(1); } - // Wrangler --json pretty-prints to stdout (`[\n {…}\n]`), so anchor - // on the first `[` followed by whitespace + `{`. Warnings go to stderr. + // `cf d1 raw` prints `[{ results: { columns, rows } }]` with rows as + // arrays; anchor on the first `[` + `{` and zip rows back into objects. const match = out.match(/\[\s*\{/); if (!match) { - console.error(`\n unexpected wrangler output (no JSON found):\n${out}`); + console.error(`\n unexpected cf output (no JSON found):\n${out}`); process.exit(1); } try { - return JSON.parse(out.slice(match.index))[0]?.results ?? []; + const { columns = [], rows = [] } = JSON.parse(out.slice(match.index))[0]?.results ?? {}; + return rows.map((row) => Object.fromEntries(columns.map((c, i) => [c, row[i]]))); } catch (e) { - console.error(`\n failed to parse wrangler output: ${e.message}`); + console.error(`\n failed to parse cf output: ${e.message}`); console.error(` raw:\n${out}`); process.exit(1); } diff --git a/wrangler.toml b/wrangler.toml deleted file mode 100644 index 6d62948..0000000 --- a/wrangler.toml +++ /dev/null @@ -1,71 +0,0 @@ -name = "htmlbin" -main = "src/index.ts" -compatibility_date = "2025-04-01" -compatibility_flags = ["nodejs_compat"] -account_id = "8a9eb8a6efdca98aa450343a55b484cc" - -# Each `wrangler versions upload` returns a workers.dev preview URL we -# can post on PRs. Production traffic still goes through the custom -# domain routes below — preview URLs are isolated workers.dev addresses. -preview_urls = true - -# Bind the worker to your custom domain. The DNS for htmlbin.dev is -# already configured under your Cloudflare account; this tells Workers -# to attach itself. -routes = [ - { pattern = "htmlbin.dev", custom_domain = true }, - { pattern = "www.htmlbin.dev", custom_domain = true } -] - -[observability] -enabled = true - -# Production values. Local dev overrides via .dev.vars, so you don't -# have to maintain two environments. -[vars] -PUBLIC_URL = "https://htmlbin.dev" -# GitHub OAuth app client id (public — appears in the browser during -# the authorize redirect, so it lives in git, not in secrets). -# Source: github.com/settings/developers → htmlbin → Client ID. -# Authorization callback URL on the app must be -# https://htmlbin.dev/auth/github/callback. -GITHUB_CLIENT_ID = "Ov23li6nAqCYrRIN3WSf" - -# Secrets (set with `wrangler secret put NAME`): -# GITHUB_CLIENT_SECRET → GitHub OAuth app client secret -# TOKEN_PEPPER → random 32+ char string used to hash API tokens - -[[kv_namespaces]] -binding = "DROPS_KV" -id = "915440d1cdfb4876bb3b8c721a694873" - -[[d1_databases]] -binding = "DB" -database_name = "htmlbin-db" -database_id = "63632af3-b786-422b-87bd-bf6e13399ec9" -# Pointing wrangler at this directory lets `wrangler d1 migrations apply` -# auto-discover migration files and track which have run via a -# `d1_migrations` table. Replaces the hardcoded-per-file npm scripts. -migrations_dir = "./migrations" - -# Workers AI — used for HTML → Markdown conversion via env.AI.toMarkdown() -# https://blog.cloudflare.com/markdown-for-agents/ -[ai] -binding = "AI" - -# Satori + resvg-wasm: dynamic PNG OG image rendering. The wasm import -# from @resvg/resvg-wasm is a binary asset; CompiledWasm tells wrangler -# to ship it as a WebAssembly.Module ready for instantiation. -[[rules]] -type = "CompiledWasm" -globs = ["**/*.wasm"] -fallthrough = true - -# Self-hosted Geist + Geist Mono fonts. -# -# We don't import the woff2 files directly — wrangler 4 + ES module Workers -# does not reliably honor [[rules]] type="Data" for imports outside src/. -# Instead, the woff2 bytes are base64-inlined into src/fonts-data.ts by -# scripts/build-fonts.mjs (regenerate after dropping new files into -# assets/fonts/). src/fonts.ts decodes once at cold start. -