diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 7fccf4b5..00000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Deploy -on: - push: - branches: main - pull_request: - branches: main - -jobs: - deploy: - name: Deploy - runs-on: ubuntu-latest - - permissions: - id-token: write # Needed for auth with Deno Deploy - contents: read # Needed to clone the repository - - steps: - - name: Clone repository - uses: actions/checkout@v4 - - - name: Install Deno - uses: denoland/setup-deno@v2 - with: - deno-version: v2.x - - - name: Install Node.js - uses: actions/setup-node@v4 - with: - node-version: lts/* - - - name: Install step - run: "npm install" - - - name: Build step - run: "npm run build" - - - name: Upload to Deno Deploy - uses: denoland/deployctl@v1 - with: - project: "profile-views" - entrypoint: "dist/server/entry.mjs" diff --git a/.gitignore b/.gitignore index dfe6d2d0..a97f4987 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,8 @@ dist .vercel # Astro build output -.astro \ No newline at end of file +.astro + +# Cloudflare wrangler +worker-configuration.d.ts +.wrangler \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index e5f2aea9..ccb0f321 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,5 @@ "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" - }, - "deno.enable": true + } } diff --git a/astro.config.ts b/astro.config.ts index 734e4be4..b936d64b 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -1,6 +1,9 @@ // https://astro.build/config +import { writeFile } from "fs/promises"; +import { EOL } from "os"; +import { fileURLToPath } from "url"; +import cloudflare from "@astrojs/cloudflare"; import vue from "@astrojs/vue"; -import deno from "@deno/astro-adapter"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "astro/config"; import compress from "astro-compressor"; @@ -8,14 +11,35 @@ import compress from "astro-compressor"; // https://astro.build/config export default defineConfig({ site: "https://views.igorkowalczyk.dev", + redirects: { "/github": "https://github.com/igorkowalczyk/views", "/docs": "https://github.com/IgorKowalczyk/github-views?tab=readme-ov-file#-basic-usage", }, - output: "server", - adapter: deno(), - integrations: [vue(), compress()], + + integrations: [ + vue(), + compress(), + { + hooks: { + "astro:build:done": async ({ dir }) => { + const outFile = fileURLToPath(new URL(".assetsignore", dir)); + await writeFile(outFile, ["_worker.js", "_routes.json", "_headers", "_redirects"].join(EOL) + EOL); + }, + }, + name: "Create .assetsignore", + }, + ], + vite: { plugins: [tailwindcss()], }, + + output: "server", + adapter: cloudflare({ + platformProxy: { + enabled: true, + configPath: "./wrangler.jsonc", + }, + }), }); diff --git a/deno.json b/deno.json deleted file mode 100644 index 838f6f5a..00000000 --- a/deno.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "deploy": { - "project": "profile-views", - "exclude": ["**/node_modules"], - "include": [], - "entrypoint": "dist/server/entry.mjs" - } -} diff --git a/package.json b/package.json index 1db0ab7f..9f715543 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,10 @@ "scripts": { "dev": "astro dev", "build": "astro build", - "preview": "deno run --allow-net --allow-read --allow-env --unstable-bare-node-builtins --unstable-kv ./dist/server/entry.mjs", + "preview": "pnpm build && wrangler dev", + "check": "pnpm build && tsc && wrangler deploy --dry-run", + "deploy": "astro build && wrangler deploy", + "types": "wrangler types", "format": "prettier . --write --ignore-unknown --cache --plugin=prettier-plugin-astro", "format:check": "prettier . --check --cache", "lint": "eslint .", @@ -21,8 +24,6 @@ "github", "profile", "astro", - "deno", - "deno-kv", "views-counter", "counter" ], @@ -33,10 +34,9 @@ }, "homepage": "https://views.igorkowalczyk.dev/", "dependencies": { + "@astrojs/cloudflare": "12.3.0", "@astrojs/vue": "5.0.7", - "@deno/astro-adapter": "0.3.0", "@tailwindcss/vite": "4.0.14", - "@types/canvas-confetti": "1.9.0", "@vueuse/core": "13.0.0", "astro": "5.5.3", "astro-compressor": "1.0.0", @@ -44,7 +44,6 @@ "canvas-confetti": "1.9.3", "class-variance-authority": "0.7.1", "clsx": "2.1.1", - "eslint-plugin-vue": "10.0.0", "lucide-vue-next": "0.483.0", "tailwind-merge": "3.0.2", "tailwindcss": "4.0.14", @@ -54,17 +53,23 @@ "@igorkowalczyk/eslint-config": "3.0.7", "@igorkowalczyk/prettier-config": "3.0.7", "@tailwindcss/forms": "0.5.10", + "@types/canvas-confetti": "1.9.0", + "@types/node": "22.13.11", "eslint": "9.22.0", + "eslint-plugin-astro": "^1.3.1", + "eslint-plugin-vue": "10.0.0", "prettier": "3.5.3", "prettier-plugin-astro": "0.14.1", "prettier-plugin-tailwindcss": "0.6.11", - "typescript": "5.8.2" + "typescript": "5.8.2", + "wrangler": "4.3.0" }, "packageManager": "pnpm@10.6.4", "pnpm": { "onlyBuiltDependencies": [ "esbuild", - "sharp" + "sharp", + "workerd" ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 060711db..735ac15c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,24 +8,21 @@ importers: .: dependencies: + '@astrojs/cloudflare': + specifier: 12.3.0 + version: 12.3.0(@types/node@22.13.11)(astro@5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) '@astrojs/vue': specifier: 5.0.7 - version: 5.0.7(astro@5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(vue@3.5.13(typescript@5.8.2))(yaml@2.7.0) - '@deno/astro-adapter': - specifier: 0.3.0 - version: 0.3.0(astro@5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0)) + version: 5.0.7(@types/node@22.13.11)(astro@5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(vue@3.5.13(typescript@5.8.2))(yaml@2.7.0) '@tailwindcss/vite': specifier: 4.0.14 - version: 4.0.14(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) - '@types/canvas-confetti': - specifier: 1.9.0 - version: 1.9.0 + version: 4.0.14(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) '@vueuse/core': specifier: 13.0.0 version: 13.0.0(vue@3.5.13(typescript@5.8.2)) astro: specifier: 5.5.3 - version: 5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) + version: 5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) astro-compressor: specifier: 1.0.0 version: 1.0.0 @@ -41,9 +38,6 @@ importers: clsx: specifier: 2.1.1 version: 2.1.1 - eslint-plugin-vue: - specifier: 10.0.0 - version: 10.0.0(eslint@9.22.0(jiti@2.4.2))(vue-eslint-parser@10.1.1(eslint@9.22.0(jiti@2.4.2))) lucide-vue-next: specifier: 0.483.0 version: 0.483.0(vue@3.5.13(typescript@5.8.2)) @@ -66,9 +60,21 @@ importers: '@tailwindcss/forms': specifier: 0.5.10 version: 0.5.10(tailwindcss@4.0.14) + '@types/canvas-confetti': + specifier: 1.9.0 + version: 1.9.0 + '@types/node': + specifier: 22.13.11 + version: 22.13.11 eslint: specifier: 9.22.0 version: 9.22.0(jiti@2.4.2) + eslint-plugin-astro: + specifier: ^1.3.1 + version: 1.3.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-vue: + specifier: 10.0.0 + version: 10.0.0(eslint@9.22.0(jiti@2.4.2))(vue-eslint-parser@10.1.1(eslint@9.22.0(jiti@2.4.2))) prettier: specifier: 3.5.3 version: 3.5.3 @@ -81,6 +87,9 @@ importers: typescript: specifier: 5.8.2 version: 5.8.2 + wrangler: + specifier: 4.3.0 + version: 4.3.0(@cloudflare/workers-types@4.20250320.0) packages: @@ -91,6 +100,11 @@ packages: '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + '@astrojs/cloudflare@12.3.0': + resolution: {integrity: sha512-HEVQnFnNiecR5cXkvENOWK1GBJsKOILmKuRFuIOh85azCse5dnVoHMmALaizjetG2JNdqTkNr+mAn7UFOM83Ig==} + peerDependencies: + astro: ^5.0.0 + '@astrojs/compiler@2.11.0': resolution: {integrity: sha512-zZOO7i+JhojO8qmlyR/URui6LyfHJY6m+L9nwyX5GiKD78YoRaZ5tzz6X0fkl+5bD3uwlDHayf6Oe8Fu36RKNg==} @@ -108,6 +122,9 @@ packages: resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} + '@astrojs/underscore-redirects@0.6.0': + resolution: {integrity: sha512-dnJgFpaM955IFNIkEEmMaaIdWXRdeZs1ID6mlGBqdjh6NiCXfKmOdq7L4fd9Dd/tr18fkLrOJ25IUJSxRAEhjQ==} + '@astrojs/vue@5.0.7': resolution: {integrity: sha512-PSES96WbJhozuGBUgMTzbAlQUdAZm0rpQjem+plsT/M0LQWpTZESZm/jf4IW7mYCtKmnAymWCH1meqsUfHCYgw==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} @@ -251,15 +268,56 @@ packages: resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} engines: {node: '>=6.9.0'} - '@deno/astro-adapter@0.3.0': - resolution: {integrity: sha512-HlN0k8XALGbzWCm58OPJBHWWpJUVXrAZRbEL/VUmZpVTl23+k3qlx7Pjdk1NcVNu1hKVl/6WTdwh9GUzd02Lpg==} + '@cloudflare/kv-asset-handler@0.4.0': + resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} + engines: {node: '>=18.0.0'} + + '@cloudflare/unenv-preset@2.2.0': + resolution: {integrity: sha512-U5/TQBjJN/HQ1JA4mzt5sTbvdT9aoucHYGbokY2JWwDkYbgoaTygYBshZpXHUo8lDppsAGdUf3pGlOc6U09HAg==} peerDependencies: - '@opentelemetry/api': ^1 - astro: ^5.0.1 + unenv: 2.0.0-rc.15 + workerd: ^1.20250310.0 peerDependenciesMeta: - '@opentelemetry/api': + workerd: optional: true + '@cloudflare/workerd-darwin-64@1.20250319.0': + resolution: {integrity: sha512-8B08kYAp1rEgXRe+YV3uCAGYa65KS8V/pajmgh5U4yULLmHryd4OPo8wf3RYl4uk5ZNbtUKR1GUNLkIraTL6Rw==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + + '@cloudflare/workerd-darwin-arm64@1.20250319.0': + resolution: {integrity: sha512-UW1c15oFYRPxwt4qEQufA/XlK5AnbVJFs7PwXo2suLXhxAdTZUKk0Mg1DgDTN65wmqQimRt4ayLVbfxFpzt0bA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + + '@cloudflare/workerd-linux-64@1.20250319.0': + resolution: {integrity: sha512-oYrTq/FP74IxaEwqHZep8sPoy5btrb8x9ubt6aYy+A1s8IHqma3bYzDmRJ8AMDl9d5+ASFqkAqB/Cj8HN1agPA==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + + '@cloudflare/workerd-linux-arm64@1.20250319.0': + resolution: {integrity: sha512-n9Qy+iA6SQSL3dRLXlkTQEHP65/i6Mk4UOFh67BOlrFJlov+/u77pyGG4koPLcuts0SnGxA0eDNlua6CN/GGAg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + + '@cloudflare/workerd-windows-64@1.20250319.0': + resolution: {integrity: sha512-MUYzPZiz3wbLtHjfc0RdO0tETTDJF9OcRPNzw8RpWba98Z1uhMX2hQ5gNQNgQJ+Y5TDMlcKHZVIJU/5E7/qcZw==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + + '@cloudflare/workers-types@4.20250320.0': + resolution: {integrity: sha512-0qYPnnF36eEzes/uLBrIE7pbyOucnyNVTlcPY4zgakZT0BBdrHYoTDGH+9VqwfcMW7mLu2PY2daYGIFsgycX2A==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} @@ -648,6 +706,10 @@ packages: resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -801,6 +863,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@next/eslint-plugin-next@15.2.1': resolution: {integrity: sha512-6ppeToFd02z38SllzWxayLxjjNfzvc7Wm07gQOKSLjyASvKcXjNStZrLXMHuaWkhjqxe+cnhb2uzfWXm1VEj/Q==} @@ -1151,6 +1216,9 @@ packages: '@types/nlcst@2.0.3': resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + '@types/node@22.13.11': + resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1330,6 +1398,15 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.14.1: resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} @@ -1391,6 +1468,9 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + as-table@1.0.55: + resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -1453,6 +1533,9 @@ packages: birpc@0.2.19: resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + blake3-wasm@2.1.5: + resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -1602,6 +1685,10 @@ packages: cookie-es@1.2.2: resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + cookie@0.7.2: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} @@ -1671,6 +1758,9 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + data-uri-to-buffer@2.0.2: + resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -2067,6 +2157,10 @@ packages: resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} engines: {node: ^18.19.0 || >=20.5.0} + exit-hook@2.2.1: + resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} + engines: {node: '>=6'} + exsolve@1.0.4: resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==} @@ -2176,6 +2270,9 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-source@2.0.12: + resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} + get-stream@9.0.1: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} @@ -2198,6 +2295,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -2788,10 +2888,20 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true + miniflare@4.20250319.0: + resolution: {integrity: sha512-xBBsl1TOkelBcSXikhvu5bQMZucXy8lXNGUgix4Fi0Fuz3d9flMpyIM7XVI5Br1BPqQ3hwwLASMOBBahAJYWag==} + engines: {node: '>=18.0.0'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2830,6 +2940,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2897,6 +3011,9 @@ packages: ofetch@1.4.1: resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + oniguruma-parser@0.5.4: resolution: {integrity: sha512-yNxcQ8sKvURiTwP0mV6bLQCYE7NKfKRRWunhbZnXgxSmB1OXa1lHrN3o4DZd+0Si0kU5blidK7BcROO8qv5TZA==} @@ -2967,6 +3084,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -3260,6 +3380,9 @@ packages: resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} engines: {node: '>=18'} + printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + prismjs@1.30.0: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} @@ -3478,6 +3601,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -3488,6 +3615,13 @@ packages: stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stacktracey@2.1.8: + resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + string-ts@2.2.1: resolution: {integrity: sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw==} @@ -3675,6 +3809,16 @@ packages: uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@5.29.0: + resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} + engines: {node: '>=14.0'} + + unenv@2.0.0-rc.15: + resolution: {integrity: sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==} + unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -3921,10 +4065,37 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + workerd@1.20250319.0: + resolution: {integrity: sha512-/+JfU0Iq+L2DWpJeBCvQIY88OkxoEV5IPbTpa+FFkBTW3eAyE7pV+DpvcvXfG94DFrA3D4z0EE9ZNwVKO5w42A==} + engines: {node: '>=16'} + hasBin: true + + wrangler@4.3.0: + resolution: {integrity: sha512-eGSj/Og4cxMF2jwstPswayU2aj9fN4FSX7rF3p+Pqe/EEVrCrs/38YsBXePbAjTs+4F8K/VvWtXYRzZ1xtZRuA==} + engines: {node: '>=18.0.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20250319.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -3960,6 +4131,9 @@ packages: resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} engines: {node: '>=18'} + youch@3.2.3: + resolution: {integrity: sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==} + zod-to-json-schema@3.24.4: resolution: {integrity: sha512-0uNlcvgabyrni9Ag8Vghj21drk7+7tp7VTwwR7KxxXXc/3pbXz2PHlDgj3cICahgF1kHm4dExBFj7BXrZJXzig==} peerDependencies: @@ -3971,6 +4145,9 @@ packages: typescript: ^4.9.4 || ^5.0.2 zod: ^3 + zod@3.22.3: + resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} + zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} @@ -3986,6 +4163,34 @@ snapshots: '@antfu/utils@0.7.10': {} + '@astrojs/cloudflare@12.3.0(@types/node@22.13.11)(astro@5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)': + dependencies: + '@astrojs/internal-helpers': 0.6.1 + '@astrojs/underscore-redirects': 0.6.0 + '@cloudflare/workers-types': 4.20250320.0 + astro: 5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) + esbuild: 0.25.1 + estree-walker: 3.0.3 + magic-string: 0.30.17 + miniflare: 4.20250319.0 + tinyglobby: 0.2.12 + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + wrangler: 4.3.0(@cloudflare/workers-types@4.20250320.0) + transitivePeerDependencies: + - '@types/node' + - bufferutil + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - utf-8-validate + - yaml + '@astrojs/compiler@2.11.0': {} '@astrojs/internal-helpers@0.6.1': {} @@ -4032,14 +4237,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/vue@5.0.7(astro@5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(vue@3.5.13(typescript@5.8.2))(yaml@2.7.0)': + '@astrojs/underscore-redirects@0.6.0': {} + + '@astrojs/vue@5.0.7(@types/node@22.13.11)(astro@5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(vue@3.5.13(typescript@5.8.2))(yaml@2.7.0)': dependencies: - '@vitejs/plugin-vue': 5.2.3(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) - '@vitejs/plugin-vue-jsx': 4.1.2(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) + '@vitejs/plugin-vue': 5.2.3(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) + '@vitejs/plugin-vue-jsx': 4.1.2(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) '@vue/compiler-sfc': 3.5.13 - astro: 5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) - vite-plugin-vue-devtools: 7.7.2(rollup@4.36.0)(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) + astro: 5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite-plugin-vue-devtools: 7.7.2(rollup@4.36.0)(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) vue: 3.5.13(typescript@5.8.2) transitivePeerDependencies: - '@nuxt/kit' @@ -4246,9 +4453,36 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@deno/astro-adapter@0.3.0(astro@5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))': + '@cloudflare/kv-asset-handler@0.4.0': + dependencies: + mime: 3.0.0 + + '@cloudflare/unenv-preset@2.2.0(unenv@2.0.0-rc.15)(workerd@1.20250319.0)': + dependencies: + unenv: 2.0.0-rc.15 + optionalDependencies: + workerd: 1.20250319.0 + + '@cloudflare/workerd-darwin-64@1.20250319.0': + optional: true + + '@cloudflare/workerd-darwin-arm64@1.20250319.0': + optional: true + + '@cloudflare/workerd-linux-64@1.20250319.0': + optional: true + + '@cloudflare/workerd-linux-arm64@1.20250319.0': + optional: true + + '@cloudflare/workerd-windows-64@1.20250319.0': + optional: true + + '@cloudflare/workers-types@4.20250320.0': {} + + '@cspotcode/source-map-support@0.8.1': dependencies: - astro: 5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0) + '@jridgewell/trace-mapping': 0.3.9 '@emnapi/runtime@1.3.1': dependencies: @@ -4548,6 +4782,8 @@ snapshots: '@eslint/core': 0.12.0 levn: 0.4.1 + '@fastify/busboy@2.1.1': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -4694,6 +4930,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@next/eslint-plugin-next@15.2.1': dependencies: fast-glob: 3.3.1 @@ -4948,13 +5189,13 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.0.14 '@tailwindcss/oxide-win32-x64-msvc': 4.0.14 - '@tailwindcss/vite@4.0.14(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))': + '@tailwindcss/vite@4.0.14(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))': dependencies: '@tailwindcss/node': 4.0.14 '@tailwindcss/oxide': 4.0.14 lightningcss: 1.29.2 tailwindcss: 4.0.14 - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) '@trysound/sax@0.2.0': {} @@ -4992,6 +5233,10 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/node@22.13.11': + dependencies: + undici-types: 6.20.0 + '@types/resolve@1.20.2': {} '@types/unist@3.0.3': {} @@ -5125,19 +5370,19 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-vue-jsx@4.1.2(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': + '@vitejs/plugin-vue-jsx@4.1.2(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': dependencies: '@babel/core': 7.26.10 '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.10) '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.26.10) - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) vue: 3.5.13(typescript@5.8.2) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.3(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': + '@vitejs/plugin-vue@5.2.3(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': dependencies: - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) vue: 3.5.13(typescript@5.8.2) '@vue/babel-helper-vue-transform-on@1.4.0': {} @@ -5199,14 +5444,14 @@ snapshots: '@vue/compiler-dom': 3.5.13 '@vue/shared': 3.5.13 - '@vue/devtools-core@7.7.2(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': + '@vue/devtools-core@7.7.2(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': dependencies: '@vue/devtools-kit': 7.7.2 '@vue/devtools-shared': 7.7.2 mitt: 3.0.1 nanoid: 5.1.5 pathe: 2.0.3 - vite-hot-client: 0.2.4(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) + vite-hot-client: 0.2.4(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) vue: 3.5.13(typescript@5.8.2) transitivePeerDependencies: - vite @@ -5266,6 +5511,10 @@ snapshots: dependencies: acorn: 8.14.1 + acorn-walk@8.3.2: {} + + acorn@8.14.0: {} + acorn@8.14.1: {} ajv@6.12.6: @@ -5338,6 +5587,10 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + as-table@1.0.55: + dependencies: + printable-characters: 1.0.42 + ast-types-flow@0.0.8: {} astro-compressor@1.0.0: {} @@ -5359,7 +5612,7 @@ snapshots: transitivePeerDependencies: - supports-color - astro@5.5.3(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0): + astro@5.5.3(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0): dependencies: '@astrojs/compiler': 2.11.0 '@astrojs/internal-helpers': 0.6.1 @@ -5411,8 +5664,8 @@ snapshots: unist-util-visit: 5.0.0 unstorage: 1.15.0 vfile: 6.0.3 - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) - vitefu: 1.0.6(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vitefu: 1.0.6(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.1 @@ -5492,6 +5745,8 @@ snapshots: birpc@0.2.19: {} + blake3-wasm@2.1.5: {} + boolbase@1.0.0: {} boxen@8.0.1: @@ -5636,6 +5891,8 @@ snapshots: cookie-es@1.2.2: {} + cookie@0.5.0: {} + cookie@0.7.2: {} copy-anything@3.0.5: @@ -5730,6 +5987,8 @@ snapshots: damerau-levenshtein@1.0.8: {} + data-uri-to-buffer@2.0.2: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -6338,6 +6597,8 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.1 + exit-hook@2.2.1: {} + exsolve@1.0.4: {} extend@3.0.2: {} @@ -6456,6 +6717,11 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-source@2.0.12: + dependencies: + data-uri-to-buffer: 2.0.2 + source-map: 0.6.1 + get-stream@9.0.1: dependencies: '@sec-ant/readable-stream': 0.4.1 @@ -6481,6 +6747,8 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regexp@0.4.1: {} + globals@11.12.0: {} globals@14.0.0: {} @@ -7251,8 +7519,27 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime@3.0.0: {} + mini-svg-data-uri@1.4.4: {} + miniflare@4.20250319.0: + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.14.0 + acorn-walk: 8.3.2 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.29.0 + workerd: 1.20250319.0 + ws: 8.18.0 + youch: 3.2.3 + zod: 3.22.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -7293,6 +7580,8 @@ snapshots: ms@2.1.3: {} + mustache@4.2.0: {} + nanoid@3.3.11: {} nanoid@5.1.5: {} @@ -7357,6 +7646,8 @@ snapshots: node-fetch-native: 1.6.6 ufo: 1.5.4 + ohash@2.0.11: {} + oniguruma-parser@0.5.4: {} oniguruma-to-es@4.1.0: @@ -7436,6 +7727,8 @@ snapshots: path-parse@1.0.7: {} + path-to-regexp@6.3.0: {} + pathe@1.1.2: {} pathe@2.0.3: {} @@ -7660,6 +7953,8 @@ snapshots: dependencies: parse-ms: 4.0.0 + printable-characters@1.0.42: {} + prismjs@1.30.0: {} prompts@2.4.2: @@ -7997,12 +8292,21 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.6.1: {} + space-separated-tokens@2.0.2: {} speakingurl@14.0.1: {} stable-hash@0.0.4: {} + stacktracey@2.1.8: + dependencies: + as-table: 1.0.55 + get-source: 2.0.12 + + stoppable@1.1.0: {} + string-ts@2.2.1: {} string-width@4.2.3: @@ -8230,6 +8534,20 @@ snapshots: uncrypto@0.1.3: {} + undici-types@6.20.0: {} + + undici@5.29.0: + dependencies: + '@fastify/busboy': 2.1.1 + + unenv@2.0.0-rc.15: + dependencies: + defu: 6.1.4 + exsolve: 1.0.4 + ohash: 2.0.11 + pathe: 2.0.3 + ufo: 1.5.4 + unicorn-magic@0.3.0: {} unified@11.0.5: @@ -8332,11 +8650,11 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-hot-client@0.2.4(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): + vite-hot-client@0.2.4(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): dependencies: - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) - vite-plugin-inspect@0.8.9(rollup@4.36.0)(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): + vite-plugin-inspect@0.8.9(rollup@4.36.0)(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): dependencies: '@antfu/utils': 0.7.10 '@rollup/pluginutils': 5.1.4(rollup@4.36.0) @@ -8347,28 +8665,28 @@ snapshots: perfect-debounce: 1.0.0 picocolors: 1.1.1 sirv: 3.0.1 - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) transitivePeerDependencies: - rollup - supports-color - vite-plugin-vue-devtools@7.7.2(rollup@4.36.0)(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)): + vite-plugin-vue-devtools@7.7.2(rollup@4.36.0)(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)): dependencies: - '@vue/devtools-core': 7.7.2(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) + '@vue/devtools-core': 7.7.2(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) '@vue/devtools-kit': 7.7.2 '@vue/devtools-shared': 7.7.2 execa: 9.5.2 sirv: 3.0.1 - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) - vite-plugin-inspect: 0.8.9(rollup@4.36.0)(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) - vite-plugin-vue-inspector: 5.3.1(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite-plugin-inspect: 0.8.9(rollup@4.36.0)(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) + vite-plugin-vue-inspector: 5.3.1(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)) transitivePeerDependencies: - '@nuxt/kit' - rollup - supports-color - vue - vite-plugin-vue-inspector@5.3.1(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): + vite-plugin-vue-inspector@5.3.1(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): dependencies: '@babel/core': 7.26.10 '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.10) @@ -8379,24 +8697,25 @@ snapshots: '@vue/compiler-dom': 3.5.13 kolorist: 1.8.0 magic-string: 0.30.17 - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) transitivePeerDependencies: - supports-color - vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0): + vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0): dependencies: esbuild: 0.25.1 postcss: 8.5.3 rollup: 4.36.0 optionalDependencies: + '@types/node': 22.13.11 fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.29.2 yaml: 2.7.0 - vitefu@1.0.6(vite@6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): + vitefu@1.0.6(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0)): optionalDependencies: - vite: 6.2.2(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) + vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.0) vue-eslint-parser@10.1.1(eslint@9.22.0(jiti@2.4.2)): dependencies: @@ -8476,12 +8795,40 @@ snapshots: word-wrap@1.2.5: {} + workerd@1.20250319.0: + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20250319.0 + '@cloudflare/workerd-darwin-arm64': 1.20250319.0 + '@cloudflare/workerd-linux-64': 1.20250319.0 + '@cloudflare/workerd-linux-arm64': 1.20250319.0 + '@cloudflare/workerd-windows-64': 1.20250319.0 + + wrangler@4.3.0(@cloudflare/workers-types@4.20250320.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.4.0 + '@cloudflare/unenv-preset': 2.2.0(unenv@2.0.0-rc.15)(workerd@1.20250319.0) + blake3-wasm: 2.1.5 + esbuild: 0.24.2 + miniflare: 4.20250319.0 + path-to-regexp: 6.3.0 + unenv: 2.0.0-rc.15 + workerd: 1.20250319.0 + optionalDependencies: + '@cloudflare/workers-types': 4.20250320.0 + fsevents: 2.3.3 + sharp: 0.33.5 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 string-width: 7.2.0 strip-ansi: 7.1.0 + ws@8.18.0: {} + xml-name-validator@4.0.0: {} xxhash-wasm@1.1.0: {} @@ -8503,6 +8850,12 @@ snapshots: yoctocolors@2.1.1: {} + youch@3.2.3: + dependencies: + cookie: 0.5.0 + mustache: 4.2.0 + stacktracey: 2.1.8 + zod-to-json-schema@3.24.4(zod@3.24.2): dependencies: zod: 3.24.2 @@ -8512,6 +8865,8 @@ snapshots: typescript: 5.8.2 zod: 3.24.2 + zod@3.22.3: {} + zod@3.24.2: {} zwitch@2.0.4: {} diff --git a/src/database/index.ts b/src/database/index.ts index a90ea92a..ca08ed11 100644 --- a/src/database/index.ts +++ b/src/database/index.ts @@ -1,16 +1,26 @@ import "./patch"; -export async function increaseViews(username: string): Promise { +export async function increaseViews(username: string, env: Cloudflare.Env): Promise { if (username === "example") return 0; - const kv = await Deno.openKv(); - await kv.atomic().sum([username], 1n).commit(); - const view = await kv.get([username]); - return Number(view.value || 0); + + const kv = env.views; + if (!kv) throw new Error("KV Namespace not available! Check your configuration - The KV namespace should be named 'views'."); + + const currentViews = Number((await kv.get(username)) || 0); + + // Increase views by 1 + const newViews = currentViews + 1; + await kv.put(username, newViews.toString()); + + return newViews; } -export async function getViews(username: string): Promise { +export async function getViews(username: string, env: Cloudflare.Env): Promise { if (username === "example") return 0; - const kv = await Deno.openKv(); - const view = await kv.get([username]); - return (view.value as number) || 0; + + const kv = env.views; + if (!kv) throw new Error("KV Namespace not available! Check your configuration - The KV namespace should be named 'views'."); + + const view = await kv.get(username); + return Number(view || 0); } diff --git a/src/env.d.ts b/src/env.d.ts index 3a96c993..76dfb60b 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,3 +1,8 @@ /// /// -/// + +type Runtime = import("@astrojs/cloudflare").Runtime; +declare namespace App { + /* eslint-disable-next-line typescript/no-empty-object-type */ + interface Locals extends Runtime {} +} diff --git a/src/pages/api/badge/[username].ts b/src/pages/api/badge/[username].ts index 6fefb7c5..87d320e0 100644 --- a/src/pages/api/badge/[username].ts +++ b/src/pages/api/badge/[username].ts @@ -1,17 +1,18 @@ +import type { APIRoute } from "astro"; import { z } from "astro/zod"; import { badgen } from "badgen"; import { increaseViews, getViews } from "@/database/index"; import { badgeCreatorSchema, formatNumber, paramsSchema } from "@/utils/utils"; -export const GET = async function GET({ params, request }: { params: { username: string }; request: Request }): Promise { +export const GET: APIRoute = async (context) => { try { - const query = new URL(request.url).searchParams; + const query = context.url.searchParams; const queryEntries = Object.fromEntries(query.entries()); - const data = badgeCreatorSchema.parse(queryEntries); - const { username } = paramsSchema.parse(params); - const views: number = data.display ? await getViews(username) : await increaseViews(username); + const { username } = paramsSchema.parse(context.params); + + const views: number = data.display ? await getViews(username, context.locals.runtime.env) : await increaseViews(username, context.locals.runtime.env); const badge = badgen({ label: data.label || "Views", diff --git a/src/pages/api/json/[username].ts b/src/pages/api/json/[username].ts index 067fcc81..214e7a04 100644 --- a/src/pages/api/json/[username].ts +++ b/src/pages/api/json/[username].ts @@ -1,11 +1,12 @@ +import type { APIRoute } from "astro"; import { getViews } from "@/database/index"; import { paramsSchema } from "@/utils/utils"; -export const GET = async function GET({ params }: { params: { username: string } }): Promise { +export const GET: APIRoute = async (context) => { try { - const { username } = paramsSchema.parse(params); + const { username } = paramsSchema.parse(context.params); - const views = await getViews(username); + const views = await getViews(username, context.locals.runtime.env); const responseBody = { views: Number(views) }; return new Response(JSON.stringify(responseBody), { diff --git a/wrangler.jsonc b/wrangler.jsonc new file mode 100644 index 00000000..f621d7f3 --- /dev/null +++ b/wrangler.jsonc @@ -0,0 +1,19 @@ +{ + "name": "views", + "compatibility_date": "2025-03-21", + "main": "./dist/_worker.js/index.js", + "observability": { + "enabled": true, + }, + "assets": { + "directory": "./dist", + "binding": "ASSETS", + }, + "upload_source_maps": true, + "kv_namespaces": [ + { + "binding": "views", + "id": "fd70ac47953b45b09a8f57cf975c6733", + }, + ], +}