From 761ab5d5b59f9c047aa4cc230e47e0a6ad985ef5 Mon Sep 17 00:00:00 2001 From: Kenzo Date: Sat, 8 Nov 2025 17:02:51 +0100 Subject: [PATCH] Refactor content structure and add basic authentication utilities - Moved event and gallery data to JSON files for cleaner content management. - Added session management utilities with CSRF protection. - Integrated OAuth-based login and logout APIs. - Updated dependencies, including Astro and introduced dotenv-cli. - Enhanced package.json with local environment support. --- .env.example | 25 + .gitignore | 1 + Dockerfile | 10 +- README.md | 96 +-- astro.config.mjs | 6 +- package-lock.json | 1017 ++++++++++++++++++---------- package.json | 10 +- public/images/pub_quiz.jpg | Bin 49822 -> 0 bytes src/components/EventsGrid.astro | 20 +- src/components/ImageCarousel.astro | 58 +- src/components/Welcome.astro | 54 +- src/content/events.json | 32 + src/content/gallery.json | 11 + src/content/texts.json | 27 + src/lib/csrf.ts | 25 + src/lib/env.ts | 29 + src/lib/session.ts | 87 +++ src/middleware.ts | 8 + src/pages/admin/index.astro | 111 +++ src/pages/api/auth/callback.ts | 83 +++ src/pages/api/auth/login.ts | 45 ++ src/pages/api/auth/logout.ts | 9 + src/pages/api/save.ts | 87 +++ src/pages/index.astro | 72 +- 24 files changed, 1374 insertions(+), 549 deletions(-) create mode 100644 .env.example delete mode 100644 public/images/pub_quiz.jpg create mode 100644 src/content/events.json create mode 100644 src/content/gallery.json create mode 100644 src/content/texts.json create mode 100644 src/lib/csrf.ts create mode 100644 src/lib/env.ts create mode 100644 src/lib/session.ts create mode 100644 src/middleware.ts create mode 100644 src/pages/admin/index.astro create mode 100644 src/pages/api/auth/callback.ts create mode 100644 src/pages/api/auth/login.ts create mode 100644 src/pages/api/auth/logout.ts create mode 100644 src/pages/api/save.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d04f2c3 --- /dev/null +++ b/.env.example @@ -0,0 +1,25 @@ +# Local development configuration for OAuth + Gitea +# Copy this file to .env.local and fill in values, then run: npm run dev:local + +PUBLIC_BASE_URL=http://localhost:4321 + +# Gitea OAuth app created with redirect URI: http://localhost:4321/api/auth/callback +OAUTH_PROVIDER=gitea +OAUTH_CLIENT_ID= +OAUTH_CLIENT_SECRET= +OAUTH_AUTHORIZE_URL=https://git.bookageek.ch/login/oauth/authorize +OAUTH_TOKEN_URL=https://git.bookageek.ch/login/oauth/access_token +OAUTH_USERINFO_URL=https://git.bookageek.ch/api/v1/user +# Optional allow-list (comma separated usernames) +# OAUTH_ALLOWED_USERS= + +# Gitea API for commits (service account PAT must have write:repository) +GITEA_BASE=https://git.bookageek.ch +GITEA_OWNER= +GITEA_REPO= +GITEA_TOKEN= +GIT_BRANCH=main + +# Secrets (use long random strings) +SESSION_SECRET= +CSRF_SECRET= diff --git a/.gitignore b/.gitignore index 016b59e..0b326b1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ pnpm-debug.log* # environment variables .env .env.production +.env.local # macOS-specific files .DS_Store diff --git a/Dockerfile b/Dockerfile index 5e532af..a6d5453 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,19 +4,17 @@ WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . -# Ensure CSS variables are present -RUN mkdir -p public/styles -RUN cp -r styles/* public/styles/ || true RUN npm run build FROM node:20-alpine AS production WORKDIR /app -RUN npm install -g serve +ENV NODE_ENV=production COPY --from=build /app/dist ./dist +# install minimal deps to run node if needed (alpine already has node) EXPOSE 3000 -CMD ["serve", "-s", "dist", "-l", "3000"] +CMD ["node", "./dist/server/entry.mjs"] -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD wget -qO- http://localhost:3000/ || exit 1 \ No newline at end of file diff --git a/README.md b/README.md index e34a99b..b99b918 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,65 @@ -# Astro Starter Kit: Minimal +# Gallus Pub Website – Admin mit Gitea OAuth und Git-Commits -```sh -npm create astro@latest -- --template minimal +Dieses Projekt stellt eine Astro‑Seite bereit und enthält eine Admin‑Oberfläche unter `/admin`, mit der Inhalte (Events, Galerie und Bilder) ohne Datenbank gepflegt werden können. Änderungen werden als Commits direkt in das Gitea‑Repository geschrieben. Woodpecker baut daraufhin und Fly.io deployt. + +## Inhalte (Headless, Git‑basiert) +- Editierbare Dateien im Repo: + - `src/content/events.json` + - `src/content/gallery.json` +- Bilder: `public/images/*` +- Die Startseite importiert diese Dateien und rendert sie. + +## Admin & Auth +- Admin‑Seite: `https:///admin` (kein Link im UI, nur direkter Pfad) +- Login via Gitea OAuth: + - `/api/auth/login` → Gitea → `/api/auth/callback` + - Session als HttpOnly‑Cookie, CSRF‑Cookie für POSTs +- Speichern: `/api/save` validiert und committet die Dateien via Gitea‑API + +## Lokale Entwicklung +1) `.env.example` nach `.env.local` kopieren und ausfüllen (Gitea OAuth‑App mit Redirect `http://localhost:4321/api/auth/callback`). +2) Installieren und starten: +```bash +npm install +npm run dev:local ``` +3) Browser öffnen: `http://localhost:4321/admin` → Mit Gitea anmelden → Inhalte bearbeiten → Speichern. -[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/minimal) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/minimal) -[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/minimal/devcontainer.json) +Hinweis: Für lokales HTTP sind Cookies ohne `Secure` gesetzt. In Produktion werden Cookies automatisch als `Secure` markiert. -> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! - -## 🚀 Project Structure - -Inside of your Astro project, you'll see the following folders and files: - -```text -/ -├── public/ -├── src/ -│ └── pages/ -│ └── index.astro -└── package.json +## Produktion (Fly.io) +- Dockerfile baut Astro als SSR und startet `node dist/server/entry.mjs` auf Port 3000. +- Secrets auf Fly.io setzen (Beispiele, Werte anpassen): ``` +flyctl secrets set \ + OAUTH_PROVIDER=gitea \ + OAUTH_CLIENT_ID=... \ + OAUTH_CLIENT_SECRET=... \ + OAUTH_AUTHORIZE_URL=https://git.bookageek.ch/login/oauth/authorize \ + OAUTH_TOKEN_URL=https://git.bookageek.ch/login/oauth/access_token \ + OAUTH_USERINFO_URL=https://git.bookageek.ch/api/v1/user \ + GITEA_BASE=https://git.bookageek.ch \ + GITEA_OWNER=OWNER \ + GITEA_REPO=REPO \ + GITEA_TOKEN=PAT \ + GIT_BRANCH=main \ + SESSION_SECRET=RANDOM \ + CSRF_SECRET=RANDOM +``` +- Optional: `PUBLIC_BASE_URL=https://gallus-pub.ch` setzen. -Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. +## Wichtige Pfad‑Konvention +- Statische Assets immer unter `public/` ablegen (z. B. `public/images/...`). +- Die Admin‑Uploads schreiben automatisch nach `public/images/*`. -There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. +## Befehle +- `npm install` – Abhängigkeiten +- `npm run dev` – Standard Dev +- `npm run dev:local` – Dev mit `.env.local` (OAuth/Gitea) +- `npm run build` – Produktion builden +- `npm run preview` – Build lokal testen -Any static assets, like images, can be placed in the `public/` directory. - -## 🧞 Commands - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :------------------------ | :----------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | -| `npm run astro -- --help` | Get help using the Astro CLI | - -## 👀 Want to learn more? - -Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). +## Sicherheit +- Kein PAT im Browser – nur serverseitig in Secrets +- CSRF‑Schutz und Pfad‑Allowlist +- Optional nutzerbasierte Zulassung: `OAUTH_ALLOWED_USERS` (Komma‑Liste) diff --git a/astro.config.mjs b/astro.config.mjs index e762ba5..bf95bbc 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,5 +1,9 @@ // @ts-check import { defineConfig } from 'astro/config'; +import node from '@astrojs/node'; // https://astro.build/config -export default defineConfig({}); +export default defineConfig({ + output: 'server', + adapter: node({ mode: 'standalone' }), +}); diff --git a/package-lock.json b/package-lock.json index cb9b17a..670ec6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,19 @@ { - "name": "Gallus_Pub", + "name": "gallus-pub", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "gallus-pub", "version": "0.0.1", "dependencies": { - "astro": "^5.12.0" + "@astrojs/node": "^9.0.0", + "astro": "^5.15.4", + "zod": "^3.23.8" + }, + "devDependencies": { + "dotenv-cli": "^7.4.2" } }, "node_modules/@astrojs/compiler": { @@ -17,23 +23,23 @@ "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.6.1.tgz", - "integrity": "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.4.tgz", + "integrity": "sha512-lDA9MqE8WGi7T/t2BMi+EAXhs4Vcvr94Gqx3q15cFEz8oFZMO4/SFBqYr/UcmNlvW+35alowkVj+w9VhLvs5Cw==", "license": "MIT" }, "node_modules/@astrojs/markdown-remark": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.3.tgz", - "integrity": "sha512-DDRtD1sPvAuA7ms2btc9A7/7DApKqgLMNrE6kh5tmkfy8utD0Z738gqd3p5aViYYdUtHIyEJ1X4mCMxfCfu15w==", + "version": "6.3.8", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.8.tgz", + "integrity": "sha512-uFNyFWadnULWK2cOw4n0hLKeu+xaVWeuECdP10cQ3K2fkybtTlhb7J7TcScdjmS8Yps7oje9S/ehYMfZrhrgCg==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.6.1", + "@astrojs/internal-helpers": "0.7.4", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", - "import-meta-resolve": "^4.1.0", + "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", @@ -42,8 +48,8 @@ "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", - "shiki": "^3.2.1", - "smol-toml": "^1.3.4", + "shiki": "^3.13.0", + "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", @@ -51,6 +57,20 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/node": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.5.0.tgz", + "integrity": "sha512-x1whLIatmCefaqJA8FjfI+P6FStF+bqmmrib0OUGM1M3cZhAXKLgPx6UF2AzQ3JgpXgCWYM24MHtraPvZhhyLQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.7.4", + "send": "^1.2.0", + "server-destroy": "^1.0.1" + }, + "peerDependencies": { + "astro": "^5.14.3" + } + }, "node_modules/@astrojs/prism": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", @@ -128,20 +148,21 @@ } }, "node_modules/@capsizecss/unpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-2.4.0.tgz", - "integrity": "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-3.0.0.tgz", + "integrity": "sha512-+ntATQe1AlL7nTOYjwjj6w3299CgRot48wL761TUGYpYgAou3AaONZazp0PKZyCyWhudWsjhq1nvRHOvbMzhTA==", "license": "MIT", "dependencies": { - "blob-to-buffer": "^1.2.8", - "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" + }, + "engines": { + "node": ">=18" } }, "node_modules/@emnapi/runtime": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", "license": "MIT", "optional": true, "dependencies": { @@ -564,10 +585,20 @@ "node": ">=18" } }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "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==", "cpu": [ "arm64" ], @@ -583,13 +614,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "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==", "cpu": [ "x64" ], @@ -605,13 +636,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "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==", "cpu": [ "arm64" ], @@ -625,9 +656,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "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==", "cpu": [ "x64" ], @@ -641,9 +672,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "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==", "cpu": [ "arm" ], @@ -657,9 +688,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "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==", "cpu": [ "arm64" ], @@ -672,10 +703,42 @@ "url": "https://opencollective.com/libvips" } }, + "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==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "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==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "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==", "cpu": [ "s390x" ], @@ -689,9 +752,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "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==", "cpu": [ "x64" ], @@ -705,9 +768,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "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==", "cpu": [ "arm64" ], @@ -721,9 +784,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "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==", "cpu": [ "x64" ], @@ -737,9 +800,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "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==", "cpu": [ "arm" ], @@ -755,13 +818,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.2.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "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==", "cpu": [ "arm64" ], @@ -777,13 +840,57 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "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==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "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==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "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==", "cpu": [ "s390x" ], @@ -799,13 +906,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "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==", "cpu": [ "x64" ], @@ -821,13 +928,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], @@ -843,13 +950,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], @@ -865,20 +972,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.7.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -887,10 +994,29 @@ "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==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "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==", "cpu": [ "ia32" ], @@ -907,9 +1033,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "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==", "cpu": [ "x64" ], @@ -926,9 +1052,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@oslojs/encoding": { @@ -1226,60 +1352,60 @@ ] }, "node_modules/@shikijs/core": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.8.1.tgz", - "integrity": "sha512-uTSXzUBQ/IgFcUa6gmGShCHr4tMdR3pxUiiWKDm8pd42UKJdYhkAYsAmHX5mTwybQ5VyGDgTjW4qKSsRvGSang==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.15.0.tgz", + "integrity": "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.8.1", + "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.8.1.tgz", - "integrity": "sha512-rZRp3BM1llrHkuBPAdYAzjlF7OqlM0rm/7EWASeCcY7cRYZIrOnGIHE9qsLz5TCjGefxBFnwgIECzBs2vmOyKA==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.15.0.tgz", + "integrity": "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.8.1", + "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.8.1.tgz", - "integrity": "sha512-KGQJZHlNY7c656qPFEQpIoqOuC4LrxjyNndRdzk5WKB/Ie87+NJCF1xo9KkOUxwxylk7rT6nhlZyTGTC4fCe1g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.15.0.tgz", + "integrity": "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.8.1", + "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.8.1.tgz", - "integrity": "sha512-TjOFg2Wp1w07oKnXjs0AUMb4kJvujML+fJ1C5cmEj45lhjbUXtziT1x2bPQb9Db6kmPhkG5NI2tgYW1/DzhUuQ==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.15.0.tgz", + "integrity": "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.8.1" + "@shikijs/types": "3.15.0" } }, "node_modules/@shikijs/themes": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.8.1.tgz", - "integrity": "sha512-Vu3t3BBLifc0GB0UPg2Pox1naTemrrvyZv2lkiSw3QayVV60me1ujFQwPZGgUTmwXl1yhCPW8Lieesm0CYruLQ==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.15.0.tgz", + "integrity": "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.8.1" + "@shikijs/types": "3.15.0" } }, "node_modules/@shikijs/types": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.8.1.tgz", - "integrity": "sha512-5C39Q8/8r1I26suLh+5TPk1DTrbY/kn3IdWA5HdizR0FhlhD05zx5nKCqhzSfDHH3p4S0ZefxWd77DLV+8FhGg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.15.0.tgz", + "integrity": "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -1516,72 +1642,72 @@ } }, "node_modules/astro": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.12.0.tgz", - "integrity": "sha512-Oov5JsMFHuUmuO+Nx6plfv3nQNK1Xl/8CgLvR8lBhZTjYnraxhuPX5COVAzbom+YLgwaDfK7KBd8zOEopRf9mg==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.15.4.tgz", + "integrity": "sha512-0g/68hLHEJZF2nYUcZM5O0kOnzCsCIf8eA9+0jfBAxp4ycujrIHRgIOdZCFKL9GoTsn8AypWbziypH5aEIF+aA==", "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.12.2", - "@astrojs/internal-helpers": "0.6.1", - "@astrojs/markdown-remark": "6.3.3", + "@astrojs/internal-helpers": "0.7.4", + "@astrojs/markdown-remark": "6.3.8", "@astrojs/telemetry": "3.3.0", - "@capsizecss/unpack": "^2.4.0", + "@capsizecss/unpack": "^3.0.0", "@oslojs/encoding": "^1.1.0", - "@rollup/pluginutils": "^5.1.4", - "acorn": "^8.14.1", + "@rollup/pluginutils": "^5.2.0", + "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", - "ci-info": "^4.2.0", + "ci-info": "^4.3.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", - "debug": "^4.4.0", + "debug": "^4.4.1", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.1.1", + "devalue": "^5.3.2", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", - "es-module-lexer": "^1.6.0", + "es-module-lexer": "^1.7.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", - "http-cache-semantics": "^4.1.1", - "import-meta-resolve": "^4.1.0", + "http-cache-semantics": "^4.2.0", + "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", - "kleur": "^4.1.5", - "magic-string": "^0.30.17", + "magic-string": "^0.30.18", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", - "package-manager-detector": "^1.1.0", - "picomatch": "^4.0.2", + "package-manager-detector": "^1.3.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.3", "prompts": "^2.4.2", "rehype": "^13.0.2", - "semver": "^7.7.1", - "shiki": "^3.2.1", - "smol-toml": "^1.3.4", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.12", - "tsconfck": "^3.1.5", + "semver": "^7.7.2", + "shiki": "^3.12.0", + "smol-toml": "^1.4.2", + "tinyexec": "^1.0.1", + "tinyglobby": "^0.2.14", + "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", - "unifont": "~0.5.0", + "unifont": "~0.6.0", "unist-util-visit": "^5.0.0", - "unstorage": "^1.15.0", + "unstorage": "^1.17.0", "vfile": "^6.0.3", - "vite": "^6.3.4", - "vitefu": "^1.0.6", + "vite": "^6.4.1", + "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", - "yocto-spinner": "^0.2.1", - "zod": "^3.24.2", - "zod-to-json-schema": "^3.24.5", + "yocto-spinner": "^0.2.3", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.24.6", "zod-to-ts": "^1.2.0" }, "bin": { @@ -1597,7 +1723,7 @@ "url": "https://opencollective.com/astrodotbuild" }, "optionalDependencies": { - "sharp": "^0.33.3" + "sharp": "^0.34.0" } }, "node_modules/axobject-query": { @@ -1645,26 +1771,6 @@ ], "license": "MIT" }, - "node_modules/blob-to-buffer": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", - "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/boxen": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", @@ -1820,51 +1926,6 @@ "node": ">=6" } }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT", - "optional": true - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -1896,13 +1957,19 @@ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", "license": "MIT" }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { - "node-fetch": "^2.7.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, "node_modules/crossws": { @@ -1975,6 +2042,15 @@ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", "license": "MIT" }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1991,9 +2067,9 @@ "license": "MIT" }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, "engines": { @@ -2013,9 +2089,9 @@ } }, "node_modules/devalue": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", - "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.4.2.tgz", + "integrity": "sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw==", "license": "MIT" }, "node_modules/devlop": { @@ -2052,6 +2128,45 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "license": "MIT" }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-cli": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.4.tgz", + "integrity": "sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6", + "dotenv": "^16.3.0", + "dotenv-expand": "^10.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "dotenv": "cli.js" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/dset": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", @@ -2061,12 +2176,27 @@ "node": ">=4" } }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/entities": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", @@ -2126,6 +2256,12 @@ "@esbuild/win32-x64": "0.25.7" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -2147,6 +2283,15 @@ "@types/estree": "^1.0.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -2215,6 +2360,15 @@ "unicode-trie": "^2.0.0" } }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2248,17 +2402,17 @@ "license": "ISC" }, "node_modules/h3": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.3.tgz", - "integrity": "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", + "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", "license": "MIT", "dependencies": { "cookie-es": "^1.2.2", - "crossws": "^0.3.4", + "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", - "node-mock-http": "^1.0.0", + "node-mock-http": "^1.0.2", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" @@ -2473,16 +2627,47 @@ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "license": "BSD-2-Clause" }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/iron-webcrypto": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", @@ -2492,13 +2677,6 @@ "url": "https://github.com/sponsors/brc-dd" } }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT", - "optional": true - }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", @@ -2568,6 +2746,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2580,15 +2765,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -2606,12 +2782,12 @@ "license": "ISC" }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "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.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magicast": { @@ -3429,6 +3605,37 @@ ], "license": "MIT" }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -3484,36 +3691,16 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-fetch-native": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz", - "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", "license": "MIT" }, "node_modules/node-mock-http": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.1.tgz", - "integrity": "sha512-0gJJgENizp4ghds/Ywu2FCmcRsgBTmRQzYPZm61wy+Em2sBarSka0OhQS5huLBg6od1zkNpnWMCZloQDFVvOMQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", + "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", "license": "MIT" }, "node_modules/normalize-path": { @@ -3526,14 +3713,14 @@ } }, "node_modules/ofetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", - "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", "license": "MIT", "dependencies": { - "destr": "^2.0.3", - "node-fetch-native": "^1.6.4", - "ufo": "^1.5.4" + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" } }, "node_modules/ohash": { @@ -3542,6 +3729,18 @@ "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", "license": "MIT" }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/oniguruma-parser": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", @@ -3644,6 +3843,16 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3737,6 +3946,15 @@ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", "license": "MIT" }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -4023,9 +4241,9 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4034,17 +4252,51 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, "license": "Apache-2.0", "optional": true, "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -4053,53 +4305,71 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@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" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/shiki": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.8.1.tgz", - "integrity": "sha512-+MYIyjwGPCaegbpBeFN9+oOifI8CKiKG3awI/6h3JeT85c//H2wDW/xCJEGuQ5jPqtbboKNqNy+JyX9PYpGwNg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.15.0.tgz", + "integrity": "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.8.1", - "@shikijs/engine-javascript": "3.8.1", - "@shikijs/engine-oniguruma": "3.8.1", - "@shikijs/langs": "3.8.1", - "@shikijs/themes": "3.8.1", - "@shikijs/types": "3.8.1", + "@shikijs/core": "3.15.0", + "@shikijs/engine-javascript": "3.15.0", + "@shikijs/engine-oniguruma": "3.15.0", + "@shikijs/langs": "3.15.0", + "@shikijs/themes": "3.15.0", + "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -4107,9 +4377,9 @@ "license": "MIT" }, "node_modules/smol-toml": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.1.tgz", - "integrity": "sha512-CxdwHXyYTONGHThDbq5XdwbFsuY4wlClRGejfE2NtwUtiHYsP1QtNsHb/hnj31jKYSchztJsaA8pSQoVzkfCFg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", + "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -4137,6 +4407,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", @@ -4190,10 +4469,13 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "license": "MIT" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinyglobby": { "version": "0.2.14", @@ -4211,11 +4493,14 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } }, "node_modules/trim-lines": { "version": "3.0.1", @@ -4353,9 +4638,9 @@ } }, "node_modules/unifont": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.5.2.tgz", - "integrity": "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.6.0.tgz", + "integrity": "sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA==", "license": "MIT", "dependencies": { "css-tree": "^3.0.0", @@ -4487,18 +4772,18 @@ } }, "node_modules/unstorage": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.16.1.tgz", - "integrity": "sha512-gdpZ3guLDhz+zWIlYP1UwQ259tG5T5vYRzDaHMkQ1bBY1SQPutvZnrRjTFaWUUpseErJIgAZS51h6NOcZVZiqQ==", + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.2.tgz", + "integrity": "sha512-cKEsD6iBWJgOMJ6vW1ID/SYuqNf8oN4yqRk8OYqaVQ3nnkJXOT1PSpaMh2QfzLs78UN5kSNRD2c/mgjT8tX7+w==", "license": "MIT", "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", - "h3": "^1.15.3", + "h3": "^1.15.4", "lru-cache": "^10.4.3", - "node-fetch-native": "^1.6.6", - "ofetch": "^1.4.1", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.0", "ufo": "^1.6.1" }, "peerDependencies": { @@ -4514,6 +4799,7 @@ "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", @@ -4558,6 +4844,9 @@ "@vercel/blob": { "optional": true }, + "@vercel/functions": { + "optional": true + }, "@vercel/kv": { "optional": true }, @@ -4621,9 +4910,9 @@ } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -4723,20 +5012,20 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/which-pm-runs": { diff --git a/package.json b/package.json index 012303d..03ec5a0 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,20 @@ { - "name": "", + "name": "gallus-pub", "type": "module", "version": "0.0.1", "scripts": { "dev": "astro dev", + "dev:local": "dotenv -e .env.local -- astro dev", "build": "astro build", "preview": "astro preview", "astro": "astro" }, "dependencies": { - "astro": "^5.12.0" + "astro": "^5.15.4", + "@astrojs/node": "^9.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "dotenv-cli": "^7.4.2" } } \ No newline at end of file diff --git a/public/images/pub_quiz.jpg b/public/images/pub_quiz.jpg deleted file mode 100644 index 5c9f05577e2a56d184dbe513cd4f6f0c9cca67d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49822 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 v7Sua(Raf03 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⪚iW88(!PeWT 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
{ - events.map((event: Event) => ( - - )) + events.length === 0 ? ( +

Keine Events vorhanden. Bitte im Admin-Bereich hinzufügen.

+ ) : ( + events.map((event: Event) => ( + + )) + ) }
diff --git a/src/components/ImageCarousel.astro b/src/components/ImageCarousel.astro index e1f994e..87e50eb 100644 --- a/src/components/ImageCarousel.astro +++ b/src/components/ImageCarousel.astro @@ -12,35 +12,41 @@ const { images = [], id } = Astro.props as { images: Image[], id?: string }; + +)} diff --git a/src/pages/api/auth/callback.ts b/src/pages/api/auth/callback.ts new file mode 100644 index 0000000..ce722e9 --- /dev/null +++ b/src/pages/api/auth/callback.ts @@ -0,0 +1,83 @@ +import type { APIRoute } from 'astro'; +import { env, getBaseUrlFromRequest } from '../../../lib/env'; +import { STATE_COOKIE, parseCookies, clearCookie, setSessionCookie, CSRF_COOKIE } from '../../../lib/session'; +import { createCsrfToken } from '../../../lib/csrf'; + +export const GET: APIRoute = async ({ request }) => { + const url = new URL(request.url); + const code = url.searchParams.get('code'); + const state = url.searchParams.get('state'); + const cookies = parseCookies(request.headers.get('cookie')); + + if (!code || !state || cookies[STATE_COOKIE] !== state) { + return new Response('Invalid OAuth state', { status: 400 }); + } + + if (!env.OAUTH_CLIENT_ID || !env.OAUTH_CLIENT_SECRET || !env.OAUTH_TOKEN_URL || !env.OAUTH_USERINFO_URL) { + return new Response('OAuth not fully configured', { status: 500 }); + } + + const redirectUri = `${getBaseUrlFromRequest(request)}/api/auth/callback`; + + // Exchange code for token + let token: string; + try { + const res = await fetch(env.OAUTH_TOKEN_URL!, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + client_id: env.OAUTH_CLIENT_ID!, + client_secret: env.OAUTH_CLIENT_SECRET!, + code, + grant_type: 'authorization_code', + redirect_uri: redirectUri, + }), + }); + if (!res.ok) { + const txt = await res.text(); + return new Response(`Token exchange failed: ${res.status} ${txt}`, { status: 500 }); + } + const data = await res.json().catch(async () => { + // Some providers may return querystring + const text = await res.text(); + const params = new URLSearchParams(text); + return { access_token: params.get('access_token') }; + }); + token = data.access_token; + if (!token) throw new Error('No access_token'); + } catch (e: any) { + return new Response(`Token error: ${e?.message || e}`, { status: 500 }); + } + + // Fetch user info + const userRes = await fetch(env.OAUTH_USERINFO_URL!, { + headers: { Authorization: `token ${token}` }, + }); + if (!userRes.ok) { + const txt = await userRes.text(); + return new Response(`Userinfo error: ${userRes.status} ${txt}`, { status: 500 }); + } + const user = await userRes.json(); + + // Optional allow list + if (env.OAUTH_ALLOWED_USERS) { + const allowed = env.OAUTH_ALLOWED_USERS.split(',').map((s) => s.trim()).filter(Boolean); + if (!allowed.includes(user?.login || user?.username)) { + return new Response('forbidden', { status: 403 }); + } + } + + // Create session and CSRF + const sessionHeader = setSessionCookie({ user: { id: user.id, username: user.login || user.username, email: user.email, displayName: user.full_name || user.name } }); + const csrf = createCsrfToken(); + // CSRF cookie should NOT be HttpOnly so frontend can read it and send in header + const csrfHeader = `${CSRF_COOKIE}=${csrf}; Path=/; SameSite=Lax${process.env.NODE_ENV === 'production' ? '; Secure' : ''}`; + + const headers = new Headers({ Location: '/admin' }); + headers.append('Set-Cookie', clearCookie(STATE_COOKIE)); + headers.append('Set-Cookie', sessionHeader); + headers.append('Set-Cookie', csrfHeader); + headers.append('Cache-Control', 'no-store'); + + return new Response(null, { status: 302, headers }); +}; diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts new file mode 100644 index 0000000..9b08065 --- /dev/null +++ b/src/pages/api/auth/login.ts @@ -0,0 +1,45 @@ +import type { APIRoute } from 'astro'; +import { env, getBaseUrlFromRequest } from '../../../lib/env'; +import { STATE_COOKIE, setTempCookie, cookieAttrs } from '../../../lib/session'; + +export const GET: APIRoute = async ({ request }) => { + if (!env.OAUTH_CLIENT_ID || !env.OAUTH_AUTHORIZE_URL) { + return new Response('OAuth not configured. Set OAUTH_CLIENT_ID and OAUTH_AUTHORIZE_URL.', { status: 500 }); + } + + const state = cryptoRandomString(); + const base = getBaseUrlFromRequest(request); + const redirectUri = `${base}/api/auth/callback`; + + let authUrl: URL; + try { + authUrl = new URL(env.OAUTH_AUTHORIZE_URL!); + } catch { + return new Response('Invalid OAUTH_AUTHORIZE_URL', { status: 500 }); + } + + authUrl.searchParams.set('client_id', env.OAUTH_CLIENT_ID!); + authUrl.searchParams.set('redirect_uri', redirectUri); + authUrl.searchParams.set('response_type', 'code'); + authUrl.searchParams.set('state', state); + + const headers = new Headers({ Location: authUrl.toString() }); + headers.append('Set-Cookie', setTempCookie(STATE_COOKIE, state, 600)); + // also ensure any previous session cookies aren't cached + headers.append('Cache-Control', 'no-store'); + + return new Response(null, { status: 302, headers }); +}; + +function cryptoRandomString(len = 24) { + const bytes = crypto.getRandomValues(new Uint8Array(len)); + return Buffer.from(bytes).toString('base64url'); +} + +// ensure Web Crypto for Node +import crypto from 'node:crypto'; +if (!(globalThis as any).crypto?.getRandomValues) { + (globalThis as any).crypto = { + getRandomValues: (arr: Uint8Array) => (crypto.webcrypto.getRandomValues(arr)) + } as any; +} diff --git a/src/pages/api/auth/logout.ts b/src/pages/api/auth/logout.ts new file mode 100644 index 0000000..e074ee0 --- /dev/null +++ b/src/pages/api/auth/logout.ts @@ -0,0 +1,9 @@ +import type { APIRoute } from 'astro'; +import { clearSessionCookie, CSRF_COOKIE, clearCookie } from '../../../lib/session'; + +export const POST: APIRoute = async () => { + const headers = new Headers(); + headers.append('Set-Cookie', clearSessionCookie()); + headers.append('Set-Cookie', clearCookie(CSRF_COOKIE)); + return new Response(JSON.stringify({ ok: true }), { status: 200, headers }); +}; diff --git a/src/pages/api/save.ts b/src/pages/api/save.ts new file mode 100644 index 0000000..a091f7d --- /dev/null +++ b/src/pages/api/save.ts @@ -0,0 +1,87 @@ +import type { APIRoute } from 'astro'; +import { env } from '../../lib/env'; +import { verifyCsrfToken } from '../../lib/csrf'; +import { parseCookies } from '../../lib/session'; +import { z } from 'zod'; + +const FileSchema = z.object({ + path: z.string(), + content: z.string(), + encoding: z.enum(['utf8', 'base64']).default('utf8'), +}); +const PayloadSchema = z.object({ + message: z.string().min(1).default('Update content'), + files: z.array(FileSchema).min(1), +}); + +function isAllowedPath(p: string): boolean { + return ( + p === 'src/content/events.json' || + p === 'src/content/gallery.json' || + p === 'src/content/texts.json' || + p.startsWith('public/images/') + ); +} + +export const POST: APIRoute = async ({ request, locals }) => { + const user = (locals as any).user; + if (!user) return new Response('unauthorized', { status: 401 }); + + const csrf = request.headers.get('x-csrf'); + const cookies = parseCookies(request.headers.get('cookie')); + if (!verifyCsrfToken(csrf || cookies['gp_csrf'])) { + return new Response('bad csrf', { status: 403 }); + } + + let payload: z.infer; + try { + const json = await request.json(); + payload = PayloadSchema.parse(json); + } catch (e: any) { + return new Response('invalid payload: ' + (e?.message || e), { status: 400 }); + } + + if (!env.GITEA_BASE || !env.GITEA_OWNER || !env.GITEA_REPO || !env.GITEA_TOKEN) { + return new Response('server not configured for Gitea', { status: 500 }); + } + + for (const f of payload.files) { + if (!isAllowedPath(f.path)) { + return new Response('path not allowed: ' + f.path, { status: 400 }); + } + } + + const results: any[] = []; + for (const f of payload.files) { + const url = `${env.GITEA_BASE}/api/v1/repos/${encodeURIComponent(env.GITEA_OWNER!)}/${encodeURIComponent(env.GITEA_REPO!)}/contents/${encodeURIComponent(f.path)}`; + const body: any = { + content: f.encoding === 'base64' ? f.content : Buffer.from(f.content, 'utf-8').toString('base64'), + message: payload.message, + branch: env.GIT_BRANCH || 'main', + author: { + name: user.displayName || user.username, + email: user.email || `${user.username}@users.noreply.local`, + }, + committer: { + name: user.displayName || user.username, + email: user.email || `${user.username}@users.noreply.local`, + } + }; + + const res = await fetch(url, { + method: 'PUT', + headers: { + Authorization: `token ${env.GITEA_TOKEN}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); + if (!res.ok) { + const text = await res.text(); + return new Response(`Gitea error for ${f.path}: ${res.status} ${text}`, { status: 500 }); + } + results.push(await res.json()); + } + + return new Response(JSON.stringify({ ok: true, results }), { status: 200, headers: { 'Content-Type': 'application/json' } }); +}; diff --git a/src/pages/index.astro b/src/pages/index.astro index a85ef67..f51fbb7 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -7,76 +7,8 @@ import Drinks from "../components/Drinks.astro"; import ImageCarousel from "../components/ImageCarousel.astro"; import Contact from "../components/Contact.astro"; import About from "../components/About.astro"; - -const events = [ - { - image: "/images/karaoke.jpg", - title: "Karaoke", - date: "Mittwoch - Samstag", - description: ` - Bei uns gibt es Karaoke Mi-Sa!!
- Seid ihr eine Gruppe und lieber unter euch? ..unseren 2.Stock kannst du auch mieten ;)
- Reserviere am besten gleich per Whatsapp 077 232 27 70 - `, - }, - { - image: "/images/pub_quiz.jpg", - title: "Pub Quiz", - date: "Jeden Freitag", - description: ` - Jeden Freitag findet unser Pub Quiz statt. Gespielt wird tischweise in 3-4 Runden.
- Jede Woche gibt es ein anderes Thema. Es geht um Ruhm und Ehre und zusätzlich werden die Sieger der Herzen durch das Publikum gekürt! <3
- Auch Einzelpersonen sind herzlich willkommen!
- *zum mitmachen minimum 1 Getränk konsumieren oder 5CHF - `, - }, - { - image: "/images/Event3.png", - title: "Karaoke tes", - date: "Mittwoch - Samstag", - description: ` - `, - }, - { - image: "/images/Event2.png", - title: "Karaoke test", - date: "Mittwoch - Samstag", - description: ` - `, - }, - { - image: "/images/Event1.png", - title: "Crepes Sucette
Live Music im Gallus Pub!", - date: "Do, 04. September 2025", - description: ` - ab 19 Uhr geht’s los, bis max. 21.30 Uhr
- Kosten? CHF 10 pro Spielgast - Reservieren unter 077 232 27 70 - `, - }, - { - image: "/images/Event4.png", - title: "Kevin McFlannigan
Live Music im Gallus Pub!", - date: "Sa, 27. September 2025", - description: ` - ab 20:00 Uhr
- Eintritt ist Frei / Hutkollekte
- Reservieren unter 077 232 27 70 - `, - }, -]; - -const images = [ - { src: "/images/Gallery7.png", alt: "Siebtes Bild" }, - { src: "/images/Gallery8.png", alt: "Achtes Bild" }, - { src: "/images/Gallery9.png", alt: "Neuntes Bild" }, - { src: "/images/Gallery6.png", alt: "Sechstes Bild" }, - { src: "/images/Gallery1.png", alt: "Erstes Bild" }, - { src: "/images/Gallery2.png", alt: "Zweites Bild" }, - { src: "/images/Gallery3.png", alt: "Drittes Bild" }, - { src: "/images/Gallery4.png", alt: "Viertes Bild" }, - { src: "/images/Gallery5.png", alt: "Fünftes Bild" }, -]; +import events from "../content/events.json"; +import images from "../content/gallery.json"; ---