initial commit

This commit is contained in:
Robert Perce 2025-05-15 07:42:32 -05:00
commit 803205ee7f
59 changed files with 3437 additions and 0 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
*.sqlite3 filter=sqlite3

4
.gitconfig Normal file
View file

@ -0,0 +1,4 @@
[filter "sqlite3"]
clean = "f() { tmpfile=$(mktemp); cat - > $tmpfile; sqlite3 $tmpfile .dump; rm $tmpfile; }; f"
smudge = "f() { tmpfile=$(mktemp); sqlite3 $tmpfile; cat $tmpfile; rm $tmpfile; }; f"
required = true

24
.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

14
astro.config.mjs Normal file
View file

@ -0,0 +1,14 @@
// @ts-check
import { defineConfig } from "astro/config";
import init from "./src/lib/db_init";
import node from "@astrojs/node";
// https://astro.build/config
export default defineConfig({
integrations: [init],
adapter: node({
mode: "standalone",
}),
});

773
bun.lock Normal file
View file

@ -0,0 +1,773 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"dependencies": {
"@astrojs/node": "^9.1.3",
"@postlight/seasons": "^1.0.0",
"@types/luxon": "^3.6.2",
"astro": "^5.5.4",
"better-auth": "^1.2.7",
"htmx.org": "2",
"luxon": "^3.6.1",
"sqids": "^0.3.0",
"unraw": "^3.0.0",
},
"devDependencies": {
"@types/bun": "^1.2.5",
"reflect-metadata": "^0.2.2",
},
},
},
"packages": {
"@astrojs/compiler": ["@astrojs/compiler@2.11.0", "", {}, "sha512-zZOO7i+JhojO8qmlyR/URui6LyfHJY6m+L9nwyX5GiKD78YoRaZ5tzz6X0fkl+5bD3uwlDHayf6Oe8Fu36RKNg=="],
"@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
"@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.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", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="],
"@astrojs/node": ["@astrojs/node@9.1.3", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "send": "^1.1.0", "server-destroy": "^1.0.1" }, "peerDependencies": { "astro": "^5.3.0" } }, "sha512-YcVxEmeZU8khNdrPYNPN3j//4tYPM+Pw6CthAJ6VE/bw65qEX7ErMRApalY2tibc3YhCeHMmsO9rXGhyW0NNyA=="],
"@astrojs/prism": ["@astrojs/prism@3.2.0", "", { "dependencies": { "prismjs": "^1.29.0" } }, "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw=="],
"@astrojs/telemetry": ["@astrojs/telemetry@3.2.0", "", { "dependencies": { "ci-info": "^4.1.0", "debug": "^4.3.7", "dlv": "^1.1.3", "dset": "^3.1.4", "is-docker": "^3.0.0", "is-wsl": "^3.1.0", "which-pm-runs": "^1.1.0" } }, "sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@babel/parser": ["@babel/parser@7.26.10", "", { "dependencies": { "@babel/types": "^7.26.10" }, "bin": "./bin/babel-parser.js" }, "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA=="],
"@babel/types": ["@babel/types@7.26.10", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ=="],
"@better-auth/utils": ["@better-auth/utils@0.2.4", "", { "dependencies": { "typescript": "^5.8.2", "uncrypto": "^0.1.3" } }, "sha512-ayiX87Xd5sCHEplAdeMgwkA0FgnXsEZBgDn890XHHwSWNqqRZDYOq3uj2Ei2leTv1I2KbG5HHn60Ah1i2JWZjQ=="],
"@better-fetch/fetch": ["@better-fetch/fetch@1.1.18", "", {}, "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="],
"@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.1", "", { "os": "android", "cpu": "arm" }, "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.1", "", { "os": "android", "cpu": "arm64" }, "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.1", "", { "os": "android", "cpu": "x64" }, "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.1", "", { "os": "linux", "cpu": "arm" }, "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.1", "", { "os": "linux", "cpu": "none" }, "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA=="],
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.1", "", { "os": "none", "cpu": "arm64" }, "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.1", "", { "os": "none", "cpu": "x64" }, "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA=="],
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg=="],
"@hexagon/base64": ["@hexagon/base64@1.1.28", "", {}, "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
"@levischuck/tiny-cbor": ["@levischuck/tiny-cbor@0.2.11", "", {}, "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow=="],
"@noble/ciphers": ["@noble/ciphers@0.6.0", "", {}, "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ=="],
"@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="],
"@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
"@peculiar/asn1-android": ["@peculiar/asn1-android@2.3.16", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw=="],
"@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA=="],
"@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg=="],
"@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.3.15", "", { "dependencies": { "asn1js": "^3.0.5", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w=="],
"@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "asn1js": "^3.0.5", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg=="],
"@postlight/seasons": ["@postlight/seasons@1.0.0", "", {}, "sha512-6+JWtyAq8tLlxm6M05w5WOoXnVhbuHGK2BJr59eJD5GscJgoeA5XslQSM2jGg60jTYfUWVpaP9OcSqZdpmnltQ=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.37.0", "", { "os": "android", "cpu": "arm" }, "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.37.0", "", { "os": "android", "cpu": "arm64" }, "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA=="],
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.37.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA=="],
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.37.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.37.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA=="],
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.37.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.37.0", "", { "os": "linux", "cpu": "arm" }, "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.37.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.37.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.37.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ=="],
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.37.0", "", { "os": "linux", "cpu": "none" }, "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA=="],
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.37.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.37.0", "", { "os": "linux", "cpu": "none" }, "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.37.0", "", { "os": "linux", "cpu": "none" }, "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.37.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.37.0", "", { "os": "linux", "cpu": "x64" }, "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.37.0", "", { "os": "linux", "cpu": "x64" }, "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.37.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.37.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.37.0", "", { "os": "win32", "cpu": "x64" }, "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA=="],
"@shikijs/core": ["@shikijs/core@3.2.1", "", { "dependencies": { "@shikijs/types": "3.2.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-FhsdxMWYu/C11sFisEp7FMGBtX/OSSbnXZDMBhGuUDBNTdsoZlMSgQv5f90rwvzWAdWIW6VobD+G3IrazxA6dQ=="],
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.2.1", "", { "dependencies": { "@shikijs/types": "3.2.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.1.0" } }, "sha512-eMdcUzN3FMQYxOmRf2rmU8frikzoSHbQDFH2hIuXsrMO+IBOCI9BeeRkCiBkcLDHeRKbOCtYMJK3D6U32ooU9Q=="],
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.2.1", "", { "dependencies": { "@shikijs/types": "3.2.1", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-wZZAkayEn6qu2+YjenEoFqj0OyQI64EWsNR6/71d1EkG4sxEOFooowKivsWPpaWNBu3sxAG+zPz5kzBL/SsreQ=="],
"@shikijs/langs": ["@shikijs/langs@3.2.1", "", { "dependencies": { "@shikijs/types": "3.2.1" } }, "sha512-If0iDHYRSGbihiA8+7uRsgb1er1Yj11pwpX1c6HLYnizDsKAw5iaT3JXj5ZpaimXSWky/IhxTm7C6nkiYVym+A=="],
"@shikijs/themes": ["@shikijs/themes@3.2.1", "", { "dependencies": { "@shikijs/types": "3.2.1" } }, "sha512-k5DKJUT8IldBvAm8WcrDT5+7GA7se6lLksR+2E3SvyqGTyFMzU2F9Gb7rmD+t+Pga1MKrYFxDIeyWjMZWM6uBQ=="],
"@shikijs/types": ["@shikijs/types@3.2.1", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-/NTWAk4KE2M8uac0RhOsIhYQf4pdU0OywQuYDGIGAJ6Mjunxl2cGiuLkvu4HLCMn+OTTLRWkjZITp+aYJv60yA=="],
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
"@simplewebauthn/browser": ["@simplewebauthn/browser@13.1.0", "", {}, "sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg=="],
"@simplewebauthn/server": ["@simplewebauthn/server@13.1.1", "", { "dependencies": { "@hexagon/base64": "^1.1.27", "@levischuck/tiny-cbor": "^0.2.2", "@peculiar/asn1-android": "^2.3.10", "@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-rsa": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-x509": "^2.3.8" } }, "sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA=="],
"@types/bun": ["@types/bun@1.2.5", "", { "dependencies": { "bun-types": "1.2.5" } }, "sha512-w2OZTzrZTVtbnJew1pdFmgV99H0/L+Pvw+z1P67HaR18MHOzYnTYOi6qzErhK8HyT+DB782ADVPPE92Xu2/Opg=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
"@types/luxon": ["@types/luxon@3.6.2", "", {}, "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw=="],
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/nlcst": ["@types/nlcst@2.0.3", "", { "dependencies": { "@types/unist": "*" } }, "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA=="],
"@types/node": ["@types/node@22.13.11", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="],
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
"ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
"array-iterate": ["array-iterate@2.0.1", "", {}, "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg=="],
"asn1js": ["asn1js@3.0.6", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA=="],
"astro": ["astro@5.5.4", "", { "dependencies": { "@astrojs/compiler": "^2.11.0", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.1", "@astrojs/telemetry": "3.2.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "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.0.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.0.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.5.3", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.2.1", "vitefu": "^1.0.6", "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.3", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-rc9Mj6dIKM9ylTSQ0/S1l5f1iSDNs0PEjRMnvVpZ0W+wfBCu99JEuXy+fiWDNT6gf60bC4dKQehZxZGdSJB9kg=="],
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
"base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="],
"better-auth": ["better-auth@1.2.7", "", { "dependencies": { "@better-auth/utils": "0.2.4", "@better-fetch/fetch": "^1.1.18", "@noble/ciphers": "^0.6.0", "@noble/hashes": "^1.6.1", "@simplewebauthn/browser": "^13.0.0", "@simplewebauthn/server": "^13.0.0", "better-call": "^1.0.8", "defu": "^6.1.4", "jose": "^5.9.6", "kysely": "^0.27.6", "nanostores": "^0.11.3", "zod": "^3.24.1" } }, "sha512-2hCB263GSrgetsMUZw8vv9O1e4S4AlYJW3P4e8bX9u3Q3idv4u9BzDFCblpTLuL4YjYovghMCN0vurAsctXOAQ=="],
"better-call": ["better-call@1.0.8", "", { "dependencies": { "@better-fetch/fetch": "^1.1.4", "rou3": "^0.5.1", "set-cookie-parser": "^2.7.1", "uncrypto": "^0.1.3" } }, "sha512-/PV8JLqDRUN7JyBPbklVsS/8E4SO3pnf8hbpa8B7xrBrr+BBYpeOAxoqtnsyk/pRs35vNB4MZx8cn9dBuNlLDA=="],
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
"bun-types": ["bun-types@1.2.5", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-3oO6LVGGRRKI4kHINx5PIdIgnLRb7l/SprhzqXapmoYkFl5m4j6EvALvbDVuuBFaamB46Ap6HCUxIXNLCGy+tg=="],
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
"chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
"character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"ci-info": ["ci-info@4.2.0", "", {}, "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg=="],
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="],
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
"cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="],
"crossws": ["crossws@0.3.4", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-uj0O1ETYX1Bh6uSgktfPvwDiPYGQ3aI4qVsaC/LWpkIzGj1nUYm5FK3K+t11oOlpN01lGbprFCH4wBlKdJjVgw=="],
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.1.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w=="],
"defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
"destr": ["destr@2.0.3", "", {}, "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ=="],
"detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
"deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="],
"devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="],
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
"diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="],
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
"dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
"emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
"emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="],
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"es-module-lexer": ["es-module-lexer@1.6.0", "", {}, "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ=="],
"esbuild": ["esbuild@0.25.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.1", "@esbuild/android-arm": "0.25.1", "@esbuild/android-arm64": "0.25.1", "@esbuild/android-x64": "0.25.1", "@esbuild/darwin-arm64": "0.25.1", "@esbuild/darwin-x64": "0.25.1", "@esbuild/freebsd-arm64": "0.25.1", "@esbuild/freebsd-x64": "0.25.1", "@esbuild/linux-arm": "0.25.1", "@esbuild/linux-arm64": "0.25.1", "@esbuild/linux-ia32": "0.25.1", "@esbuild/linux-loong64": "0.25.1", "@esbuild/linux-mips64el": "0.25.1", "@esbuild/linux-ppc64": "0.25.1", "@esbuild/linux-riscv64": "0.25.1", "@esbuild/linux-s390x": "0.25.1", "@esbuild/linux-x64": "0.25.1", "@esbuild/netbsd-arm64": "0.25.1", "@esbuild/netbsd-x64": "0.25.1", "@esbuild/openbsd-arm64": "0.25.1", "@esbuild/openbsd-x64": "0.25.1", "@esbuild/sunos-x64": "0.25.1", "@esbuild/win32-arm64": "0.25.1", "@esbuild/win32-ia32": "0.25.1", "@esbuild/win32-x64": "0.25.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ=="],
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
"escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
"fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="],
"flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="],
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="],
"github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="],
"h3": ["h3@1.15.1", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.3", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3" } }, "sha512-+ORaOBttdUm1E2Uu/obAyCguiI7MbBvsLTndc3gyK3zU+SYLoZXlyCP9Xgy0gikkGufFLTZXCXD6+4BsufnmHA=="],
"hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="],
"hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="],
"hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="],
"hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="],
"hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="],
"hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
"hast-util-to-parse5": ["hast-util-to-parse5@8.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw=="],
"hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="],
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
"hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
"html-escaper": ["html-escaper@3.0.3", "", {}, "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="],
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
"htmx.org": ["htmx.org@2.0.4", "", {}, "sha512-HLxMCdfXDOJirs3vBZl/ZLoY+c7PfM4Ahr2Ad4YXh6d22T5ltbTXFFkpx9Tgb2vvmWFMbIc3LqN2ToNkZJvyYQ=="],
"http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="],
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
"import-meta-resolve": ["import-meta-resolve@4.1.0", "", {}, "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw=="],
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
"iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
"jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"kysely": ["kysely@0.27.6", "", {}, "sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ=="],
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="],
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
"magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="],
"markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
"mdast-util-definitions": ["mdast-util-definitions@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="],
"mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="],
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="],
"mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="],
"mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="],
"mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="],
"mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="],
"mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="],
"mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="],
"mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="],
"mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
"mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="],
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
"micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="],
"micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="],
"micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="],
"micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="],
"micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="],
"micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="],
"micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="],
"micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="],
"micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="],
"micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="],
"micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="],
"micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="],
"micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
"micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="],
"micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="],
"micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="],
"micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="],
"micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="],
"micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
"micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="],
"micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="],
"micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="],
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
"micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="],
"micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
"mime-types": ["mime-types@3.0.1", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA=="],
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"nanostores": ["nanostores@0.11.4", "", {}, "sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ=="],
"neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
"nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="],
"node-fetch-native": ["node-fetch-native@1.6.6", "", {}, "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="],
"node-mock-http": ["node-mock-http@1.0.0", "", {}, "sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ=="],
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"ofetch": ["ofetch@1.4.1", "", { "dependencies": { "destr": "^2.0.3", "node-fetch-native": "^1.6.4", "ufo": "^1.5.4" } }, "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw=="],
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
"oniguruma-parser": ["oniguruma-parser@0.5.4", "", {}, "sha512-yNxcQ8sKvURiTwP0mV6bLQCYE7NKfKRRWunhbZnXgxSmB1OXa1lHrN3o4DZd+0Si0kU5blidK7BcROO8qv5TZA=="],
"oniguruma-to-es": ["oniguruma-to-es@4.1.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "oniguruma-parser": "^0.5.4", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-SNwG909cSLo4vPyyPbU/VJkEc9WOXqu2ycBlfd1UCXLqk1IijcQktSBb2yRQ2UFPsDhpkaf+C1dtT3PkLK/yWA=="],
"p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="],
"p-queue": ["p-queue@8.1.0", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw=="],
"p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="],
"package-manager-detector": ["package-manager-detector@1.1.0", "", {}, "sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA=="],
"parse-latin": ["parse-latin@7.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "@types/unist": "^3.0.0", "nlcst-to-string": "^4.0.0", "unist-util-modify-children": "^4.0.0", "unist-util-visit-children": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ=="],
"parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
"prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="],
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
"property-information": ["property-information@7.0.0", "", {}, "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg=="],
"pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="],
"pvutils": ["pvutils@1.1.3", "", {}, "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ=="],
"radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="],
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="],
"regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="],
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
"regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
"rehype": ["rehype@13.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "rehype-parse": "^9.0.0", "rehype-stringify": "^10.0.0", "unified": "^11.0.0" } }, "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A=="],
"rehype-parse": ["rehype-parse@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", "unified": "^11.0.0" } }, "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag=="],
"rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="],
"rehype-stringify": ["rehype-stringify@10.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-html": "^9.0.0", "unified": "^11.0.0" } }, "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA=="],
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
"remark-rehype": ["remark-rehype@11.1.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ=="],
"remark-smartypants": ["remark-smartypants@3.0.2", "", { "dependencies": { "retext": "^9.0.0", "retext-smartypants": "^6.0.0", "unified": "^11.0.4", "unist-util-visit": "^5.0.0" } }, "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA=="],
"remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
"retext": ["retext@9.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "retext-latin": "^4.0.0", "retext-stringify": "^4.0.0", "unified": "^11.0.0" } }, "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA=="],
"retext-latin": ["retext-latin@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "parse-latin": "^7.0.0", "unified": "^11.0.0" } }, "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA=="],
"retext-smartypants": ["retext-smartypants@6.2.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ=="],
"retext-stringify": ["retext-stringify@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unified": "^11.0.0" } }, "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA=="],
"rollup": ["rollup@4.37.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.37.0", "@rollup/rollup-android-arm64": "4.37.0", "@rollup/rollup-darwin-arm64": "4.37.0", "@rollup/rollup-darwin-x64": "4.37.0", "@rollup/rollup-freebsd-arm64": "4.37.0", "@rollup/rollup-freebsd-x64": "4.37.0", "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", "@rollup/rollup-linux-arm-musleabihf": "4.37.0", "@rollup/rollup-linux-arm64-gnu": "4.37.0", "@rollup/rollup-linux-arm64-musl": "4.37.0", "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", "@rollup/rollup-linux-riscv64-gnu": "4.37.0", "@rollup/rollup-linux-riscv64-musl": "4.37.0", "@rollup/rollup-linux-s390x-gnu": "4.37.0", "@rollup/rollup-linux-x64-gnu": "4.37.0", "@rollup/rollup-linux-x64-musl": "4.37.0", "@rollup/rollup-win32-arm64-msvc": "4.37.0", "@rollup/rollup-win32-ia32-msvc": "4.37.0", "@rollup/rollup-win32-x64-msvc": "4.37.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg=="],
"rou3": ["rou3@0.5.1", "", {}, "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ=="],
"semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"send": ["send@1.2.0", "", { "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" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="],
"server-destroy": ["server-destroy@1.0.1", "", {}, "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ=="],
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
"shiki": ["shiki@3.2.1", "", { "dependencies": { "@shikijs/core": "3.2.1", "@shikijs/engine-javascript": "3.2.1", "@shikijs/engine-oniguruma": "3.2.1", "@shikijs/langs": "3.2.1", "@shikijs/themes": "3.2.1", "@shikijs/types": "3.2.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-VML/2o1/KGYkEf/stJJ+s9Ypn7jUKQPomGLGYso4JJFMFxVDyPNsjsI3MB3KLjlMOeH44gyaPdXC6rik2WXvUQ=="],
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
"smol-toml": ["smol-toml@1.3.1", "", {}, "sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"sqids": ["sqids@0.3.0", "", {}, "sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw=="],
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
"tinyglobby": ["tinyglobby@0.2.12", "", { "dependencies": { "fdir": "^6.4.3", "picomatch": "^4.0.2" } }, "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww=="],
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
"tsconfck": ["tsconfck@3.1.5", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"type-fest": ["type-fest@4.37.0", "", {}, "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg=="],
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
"ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="],
"ultrahtml": ["ultrahtml@1.5.3", "", {}, "sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg=="],
"uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
"unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="],
"unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="],
"unist-util-modify-children": ["unist-util-modify-children@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "array-iterate": "^2.0.0" } }, "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw=="],
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
"unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="],
"unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
"unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
"unist-util-visit-children": ["unist-util-visit-children@3.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA=="],
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="],
"unraw": ["unraw@3.0.0", "", {}, "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg=="],
"unstorage": ["unstorage@1.15.0", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.3", "h3": "^1.15.0", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.6", "ofetch": "^1.4.1", "ufo": "^1.5.4" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-m40eHdGY/gA6xAPqo8eaxqXgBuzQTlAKfmB1iF7oCKXE1HfwHwzDJBywK+qQGn52dta+bPlZluPF7++yR3p/bg=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
"vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="],
"vite": ["vite@6.2.2", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ=="],
"vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="],
"web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
"which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="],
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
"wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="],
"xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
"yocto-spinner": ["yocto-spinner@0.2.1", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-lHHxjh0bXaLgdJy3cNnVb/F9myx3CkhrvSOEVTkaUgNMXnYFa2xYPVhtGnqhh3jErY2gParBOHallCbc7NrlZQ=="],
"yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="],
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
"zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="],
"zod-to-ts": ["zod-to-ts@1.2.0", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"ansi-align/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
}
}

237
file.sqlite3 Normal file
View file

@ -0,0 +1,237 @@
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE pages(
id integer primary key autoincrement,
name text unique,
route text unique , reset_schedule text);
INSERT INTO pages VALUES(1,'Daily','','daily');
INSERT INTO pages VALUES(2,'Main Room','main','weekly');
INSERT INTO pages VALUES(3,'Bathrooms','bathrooms','weekly');
INSERT INTO pages VALUES(4,'Bedrooms','bedrooms','weekly');
INSERT INTO pages VALUES(5,'Fitness','fitness','weekly');
INSERT INTO pages VALUES(6,'Fortnightly','fortnightly','fortnightly');
INSERT INTO pages VALUES(7,'Monthly','monthly','monthly');
INSERT INTO pages VALUES(8,'Seasonally','seasonally','seasonally');
CREATE TABLE questlines(
id integer primary key autoincrement,
coins_reward integer,
claimed bool,
name text unique,
page_id integer,
foreign key(page_id) references page(id) );
INSERT INTO questlines VALUES(1,20,0,'Mornings',1);
INSERT INTO questlines VALUES(2,20,0,'Dailies',1);
INSERT INTO questlines VALUES(3,35,0,'Kitchen',2);
INSERT INTO questlines VALUES(4,35,0,'Big Room',2);
INSERT INTO questlines VALUES(5,35,0,'External doors',2);
INSERT INTO questlines VALUES(7,20,0,'Bathrooms',3);
INSERT INTO questlines VALUES(8,25,0,'Bedrooms',4);
INSERT INTO questlines VALUES(9,30,0,'Hallway',4);
INSERT INTO questlines VALUES(10,15,0,'Fitness 3',5);
INSERT INTO questlines VALUES(11,100,0,'Fortnightly',6);
INSERT INTO questlines VALUES(12,300,0,'Monthly',7);
INSERT INTO questlines VALUES(13,600,0,'Seasonally',8);
CREATE TABLE quests(
id integer primary key autoincrement,
name text,
coins_reward integer,
questline_id integer,
completed bool,
claimed bool,
sort_order integer,
foreign key(questline_id) references questlines(id)
unique(name, questline_id) );
INSERT INTO quests VALUES(1,'Bed',5,1,0,0,NULL);
INSERT INTO quests VALUES(2,'Brush',10,1,0,0,NULL);
INSERT INTO quests VALUES(3,'Laundry',15,1,0,0,NULL);
INSERT INTO quests VALUES(4,'Outside',20,1,0,0,NULL);
INSERT INTO quests VALUES(5,'Yoga',25,1,0,0,NULL);
INSERT INTO quests VALUES(6,'Cleandish',15,2,0,0,NULL);
INSERT INTO quests VALUES(7,'Floss',10,2,0,0,NULL);
INSERT INTO quests VALUES(8,'Read-a-page',5,2,0,0,NULL);
INSERT INTO quests VALUES(9,'Tidy',50,3,0,0,NULL);
INSERT INTO quests VALUES(10,'Wipe counter',10,3,0,0,NULL);
INSERT INTO quests VALUES(11,'Clean sink',15,3,0,0,NULL);
INSERT INTO quests VALUES(12,'Dining: Tidy',15,4,0,0,NULL);
INSERT INTO quests VALUES(13,'Wipe table',10,4,0,0,NULL);
INSERT INTO quests VALUES(14,'Living: Tidy',15,4,0,0,NULL);
INSERT INTO quests VALUES(15,'Vac hard floors & rug',25,4,0,0,NULL);
INSERT INTO quests VALUES(16,'Tidy entry tables',20,5,0,0,NULL);
INSERT INTO quests VALUES(17,'Vac stairs',15,5,0,0,NULL);
INSERT INTO quests VALUES(18,'Patio leaves',35,5,0,0,NULL);
INSERT INTO quests VALUES(19,'Cover grill',5,5,0,0,NULL);
INSERT INTO quests VALUES(20,'Tidy primary',20,7,0,0,NULL);
INSERT INTO quests VALUES(21,'Tidy hall',20,7,0,0,NULL);
INSERT INTO quests VALUES(22,'Tidy upstairs',10,7,0,0,NULL);
INSERT INTO quests VALUES(23,'Counter primary',10,7,0,0,NULL);
INSERT INTO quests VALUES(24,'Counter hall',10,7,0,0,NULL);
INSERT INTO quests VALUES(25,'Counter upstairs',10,7,0,0,NULL);
INSERT INTO quests VALUES(26,'Trash primary',10,7,0,0,NULL);
INSERT INTO quests VALUES(27,'Trash hall',10,7,0,0,NULL);
INSERT INTO quests VALUES(28,'Trash upstairs',10,7,0,0,NULL);
INSERT INTO quests VALUES(29,'Floor primary',10,7,0,0,NULL);
INSERT INTO quests VALUES(30,'Floor hall',10,7,0,0,NULL);
INSERT INTO quests VALUES(31,'Floor upstairs',10,7,0,0,NULL);
INSERT INTO quests VALUES(32,'Wash towels',10,7,0,0,NULL);
INSERT INTO quests VALUES(33,'Tidy primary',30,8,0,0,NULL);
INSERT INTO quests VALUES(34,'Sheets primary',20,8,0,0,NULL);
INSERT INTO quests VALUES(35,'Vac primary',15,8,0,0,NULL);
INSERT INTO quests VALUES(36,'Tidy nursery',20,8,0,0,NULL);
INSERT INTO quests VALUES(37,'Vac nursery',5,8,0,0,NULL);
INSERT INTO quests VALUES(38,'Tidy/sheets guest',15,8,0,0,NULL);
INSERT INTO quests VALUES(39,'Tidy upliving',10,8,0,0,NULL);
INSERT INTO quests VALUES(40,'Tidy office',20,9,0,0,NULL);
INSERT INTO quests VALUES(41,'Vac office',15,9,0,0,NULL);
INSERT INTO quests VALUES(42,'Tidy studio',15,9,0,0,NULL);
INSERT INTO quests VALUES(43,'Tidy workshop',20,9,0,0,NULL);
INSERT INTO quests VALUES(44,'Deads',5,10,0,0,NULL);
INSERT INTO quests VALUES(45,'Curls',5,10,0,0,NULL);
INSERT INTO quests VALUES(46,'Squat',5,10,0,0,NULL);
INSERT INTO quests VALUES(47,'OHP',25,10,0,0,NULL);
INSERT INTO quests VALUES(48,'Cardio 1',5,10,0,0,NULL);
INSERT INTO quests VALUES(49,'Cardio 2',5,10,0,0,NULL);
INSERT INTO quests VALUES(50,'Cardio 3',15,10,0,0,NULL);
INSERT INTO quests VALUES(51,'Sani sponge; clean microwave',15,11,0,0,NULL);
INSERT INTO quests VALUES(52,'Mirrors',20,11,0,0,NULL);
INSERT INTO quests VALUES(53,'Toilets',20,11,0,0,NULL);
INSERT INTO quests VALUES(54,'Coffee/bar & mat',5,11,0,0,NULL);
INSERT INTO quests VALUES(55,'Lawnmow',25,11,0,0,NULL);
INSERT INTO quests VALUES(56,'Lawn edging',25,11,0,0,NULL);
INSERT INTO quests VALUES(57,'Vac laundry',5,5,0,0,NULL);
CREATE TABLE events(
id integer primary key autoincrement,
record_time datetime not null default current_timestamp,
kind text,
quest_id integer,
questline_id integer,
coins_claimed integer, coins_spent integer, gems_claimed integer, gems_spent integer, reward_id integer,
foreign key(quest_id) references quest(id) );
INSERT INTO events VALUES(1,'2025-04-01 21:21:12','complete_quest',9,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(2,'2025-04-01 21:21:13','complete_quest',9,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(3,'2025-04-01 21:51:45','from_spreadsheet',NULL,NULL,675,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(4,'2025-04-01 21:52:44','from_spreadsheet',NULL,NULL,NULL,NULL,830,NULL,NULL);
INSERT INTO events VALUES(5,'2025-04-02 15:44:53','claim_quest',1,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(6,'2025-04-02 15:44:53','claim_quest',2,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(7,'2025-04-02 15:44:53','claim_quest',3,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(8,'2025-04-02 15:44:53','claim_quest',4,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(9,'2025-04-02 15:44:53','claim_quest',5,NULL,25,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(10,'2025-04-02 15:44:53','claim_quest',6,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(11,'2025-04-02 15:44:53','claim_quest',8,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(12,'2025-04-02 15:44:53','claim_questline',NULL,1,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(13,'2025-04-04 16:22:04','claim_quest',1,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(14,'2025-04-04 16:22:04','claim_quest',2,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(15,'2025-04-04 16:22:04','claim_quest',3,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(16,'2025-04-04 16:22:04','claim_quest',4,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(17,'2025-04-04 16:22:04','claim_quest',5,NULL,25,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(18,'2025-04-04 16:22:04','claim_quest',6,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(19,'2025-04-04 16:22:04','claim_quest',7,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(20,'2025-04-04 16:22:04','claim_quest',8,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(21,'2025-04-04 16:22:04','claim_questline',NULL,1,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(22,'2025-04-04 16:22:04','claim_questline',NULL,2,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(23,'2025-04-05 05:07:48','claim_quest',1,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(24,'2025-04-05 05:08:00','claim_quest',3,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(25,'2025-04-05 05:08:05','claim_quest',5,NULL,25,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(26,'2025-04-05 05:09:32','claim_questline',NULL,1,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(27,'2025-04-05 05:09:33','claim_quest',2,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(28,'2025-04-05 05:09:34','claim_quest',4,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(29,'2025-04-05 05:09:38','claim_quest',7,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(30,'2025-04-05 05:09:38','claim_quest',8,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(31,'2025-04-05 05:10:08','claim_quest',10,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(32,'2025-04-05 05:10:09','claim_questline',NULL,3,35,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(33,'2025-04-05 05:10:10','claim_quest',11,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(34,'2025-04-05 05:12:57','claim_quest',44,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(35,'2025-04-05 05:12:57','claim_quest',45,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(36,'2025-04-05 05:12:57','claim_quest',46,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(37,'2025-04-05 05:12:57','claim_quest',47,NULL,25,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(38,'2025-04-05 05:12:57','claim_quest',48,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(39,'2025-04-05 05:12:57','claim_quest',49,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(40,'2025-04-05 05:12:57','claim_quest',50,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(41,'2025-04-05 05:12:57','claim_questline',NULL,10,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(42,'2025-04-05 21:11:28','gacha_pull',NULL,NULL,NULL,100,25,NULL,NULL);
INSERT INTO events VALUES(43,'2025-04-05 21:13:14','gacha_pull',NULL,NULL,NULL,100,25,NULL,NULL);
INSERT INTO events VALUES(44,'2025-04-05 21:28:26','gacha_pull',NULL,NULL,NULL,100,NULL,NULL,5);
INSERT INTO events VALUES(45,'2025-04-05 21:28:51','gacha_pull',NULL,NULL,NULL,100,NULL,NULL,5);
INSERT INTO events VALUES(46,'2025-04-05 21:29:28','gacha_pull',NULL,NULL,NULL,100,80,NULL,NULL);
INSERT INTO events VALUES(47,'2025-04-05 21:29:32','gacha_pull',NULL,NULL,NULL,100,80,NULL,NULL);
INSERT INTO events VALUES(48,'2025-04-05 21:29:33','gacha_pull',NULL,NULL,NULL,100,25,NULL,NULL);
INSERT INTO events VALUES(49,'2025-04-06 05:57:07','gacha_pull',NULL,NULL,NULL,100,80,NULL,NULL);
INSERT INTO events VALUES(50,'2025-04-06 05:57:10','gacha_pull',NULL,NULL,NULL,100,135,NULL,NULL);
INSERT INTO events VALUES(51,'2025-04-06 05:57:12','gacha_pull',NULL,NULL,NULL,100,280,NULL,NULL);
INSERT INTO events VALUES(52,'2025-04-06 05:57:14','gacha_pull',NULL,NULL,NULL,100,80,NULL,NULL);
INSERT INTO events VALUES(53,'2025-04-06 16:14:56','claim_quest',1,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(54,'2025-04-06 16:14:56','claim_quest',2,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(55,'2025-04-06 16:14:56','claim_quest',3,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(56,'2025-04-06 16:14:56','claim_quest',4,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(57,'2025-04-06 16:14:56','claim_quest',6,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(58,'2025-04-06 16:14:56','claim_quest',7,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(59,'2025-04-06 16:14:56','claim_quest',8,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(60,'2025-04-06 16:14:56','claim_questline',NULL,2,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(61,'2025-04-07 05:38:48','claim_quest',20,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(62,'2025-04-07 05:38:48','claim_quest',21,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(63,'2025-04-07 05:38:48','claim_quest',22,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(64,'2025-04-07 05:38:48','claim_quest',23,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(65,'2025-04-07 05:38:48','claim_quest',24,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(66,'2025-04-07 05:38:48','claim_quest',25,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(67,'2025-04-07 05:38:48','claim_quest',26,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(68,'2025-04-07 05:38:48','claim_quest',27,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(69,'2025-04-07 05:38:48','claim_quest',28,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(70,'2025-04-07 05:38:48','claim_quest',29,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(71,'2025-04-07 05:38:48','claim_quest',30,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(72,'2025-04-07 05:38:48','claim_quest',31,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(73,'2025-04-07 05:42:36','claim_quest',39,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(74,'2025-04-07 05:42:37','claim_quest',34,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(75,'2025-04-07 05:44:12','claim_quest',14,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(76,'2025-04-07 05:44:14','claim_quest',13,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(77,'2025-04-07 05:44:14','claim_quest',12,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(78,'2025-04-08 01:24:54','claim_quest',1,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(79,'2025-04-08 01:24:54','claim_quest',2,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(80,'2025-04-08 01:24:54','claim_quest',3,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(81,'2025-04-08 01:24:54','claim_quest',4,NULL,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(82,'2025-04-08 01:24:54','claim_quest',5,NULL,25,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(83,'2025-04-08 01:24:54','claim_quest',6,NULL,15,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(84,'2025-04-08 01:24:54','claim_quest',7,NULL,10,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(85,'2025-04-08 01:24:54','claim_quest',8,NULL,5,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(86,'2025-04-08 01:24:54','claim_questline',NULL,1,20,NULL,NULL,NULL,NULL);
INSERT INTO events VALUES(87,'2025-04-08 01:24:54','claim_questline',NULL,2,20,NULL,NULL,NULL,NULL);
CREATE TABLE rewards(
id integer primary key autoincrement,
state integer not null default 2,
name text,
link text,
cents integer,
gems_cost integer,
rarity real,
chance real , sort_order integer);
INSERT INTO rewards VALUES(1,2,'Boba','',800,1600,0.390625,0.1515377888007329587,1);
INSERT INTO rewards VALUES(2,2,'Classical record',NULL,1000,2000,0.25,0.0969841848324690947,2);
INSERT INTO rewards VALUES(3,2,'Modern record','',3000,6000,0.02777777777777777624,0.01077602053694101148,3);
INSERT INTO rewards VALUES(4,2,'Onigiri lunch','',1000,2000,0.25,0.0969841848324690947,5);
INSERT INTO rewards VALUES(5,2,'Chaat lunch','',650,1300,0.5917159763313609711,0.2295483664673824976,6);
INSERT INTO rewards VALUES(6,2,'Asahi soft-serve','',500,1000,1.0,0.3879367393298763788,7);
INSERT INTO rewards VALUES(7,2,'Katabatic Flex 40','https://katabaticgear.com/products/flex-40-f',35000,70000,0.000204081632653061232,7.917076312854621112e-05,8);
INSERT INTO rewards VALUES(8,2,'Featherweight bag','https://singer-featherweight.com/products/bag-padded-travel-fits-singer-featherweight-221-222-includes-foot-controller-pouch',7500,15000,0.004444444444444444441,0.001724163285910561846,9);
INSERT INTO rewards VALUES(9,2,'Miicoffee DF54','https://miicoffee.shop/products/miicoffee-df54-single-dose-coffee-grinder?variant=49254366904615',23000,46000,0.0004725897920604915061,0.0001833349429725313886,10);
INSERT INTO rewards VALUES(10,2,'New book','',2000,4000,0.0625,0.02424604620811727367,4);
CREATE TABLE inventory(
id integer primary key autoincrement,
reward_id integer, state text,
foreign key(reward_id) references rewards(id) );
INSERT INTO inventory VALUES(1,5,NULL);
INSERT INTO inventory VALUES(2,5,NULL);
INSERT INTO sqlite_sequence VALUES('pages',8);
INSERT INTO sqlite_sequence VALUES('questlines',13);
INSERT INTO sqlite_sequence VALUES('quests',57);
INSERT INTO sqlite_sequence VALUES('events',87);
INSERT INTO sqlite_sequence VALUES('rewards',10);
INSERT INTO sqlite_sequence VALUES('inventory',2);
CREATE TRIGGER insert_reward_chances after insert on rewards begin
update rewards set gems_cost = cents * 2 where id = NEW.id;
update rewards set rarity = 100 / pow(gems_cost / 100, 2) where id = NEW.id;
update rewards set chance = rarity / (select sum(rarity) from rewards); end;
CREATE TRIGGER update_reward_chances after update of cents on rewards begin
update rewards set gems_cost = cents * 2 where id = NEW.id;
update rewards set rarity = 100 / pow(gems_cost / 100, 2) where id = NEW.id;
update rewards set chance = rarity / (select sum(rarity) from rewards); end;
CREATE TRIGGER pull_rewards_to_inventory after update of reward_id on events when NEW.kind = 'gacha_pull' begin
insert into inventory (reward_id) values (NEW.reward_id); end;
COMMIT;

26
package.json Normal file
View file

@ -0,0 +1,26 @@
{
"name": "",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/node": "^9.1.3",
"@postlight/seasons": "^1.0.0",
"@types/luxon": "^3.6.2",
"astro": "^5.5.4",
"better-auth": "^1.2.7",
"htmx.org": "2",
"luxon": "^3.6.1",
"sqids": "^0.3.0",
"unraw": "^3.0.0"
},
"devDependencies": {
"@types/bun": "^1.2.5",
"reflect-metadata": "^0.2.2"
}
}

9
public/favicon.svg Normal file
View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse rx="8.5" ry="9" transform="matrix(-1 0 0 1 10.5 12)" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 8.8C12.3732 8.29767 11.5941 8 10.7498 8C8.67883 8 7 9.79086 7 12C7 14.2091 8.67883 16 10.7498 16C11.5941 16 12.3732 15.7023 13 15.2" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 3C14.6667 3 22 3.9 22 12C22 20.1 14.6667 21 11 21" stroke="#000000" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 702 B

BIN
public/static/epic.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

4
public/static/gem.svg Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.21913 4.3753C5.40891 4.13809 5.69622 4 6 4H12H18C18.3038 4 18.5911 4.13809 18.7809 4.3753L22.7809 9.37531C23.0879 9.75907 23.0705 10.309 22.7399 10.6727L12.7399 21.6727C12.5504 21.8811 12.2817 22 12 22C11.7183 22 11.4496 21.8811 11.2601 21.6727L1.26006 10.6727C0.929475 10.309 0.912125 9.75907 1.21913 9.37531L5.21913 4.3753ZM6.48063 6L4.08063 9H7.51938L9.91938 6H6.48063ZM12 6.60078L10.0806 9H13.9194L12 6.60078ZM14.5723 11H9.4277L12 18.0738L14.5723 11ZM9.32559 16.5715L7.29957 11H4.26055L9.32559 16.5715ZM14.6744 16.5715L16.7004 11H19.7395L14.6744 16.5715ZM19.9194 9H16.4806L14.0806 6H17.5194L19.9194 9Z" fill="#000000" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
public/static/rare.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

View file

@ -0,0 +1,22 @@
---
import Icon from './Icon.astro';
const { class: className, chorecoin, gem } = Astro.props
---
<div class={className}>
<span><slot /></span>
<Icon {...{chorecoin, gem}} />
</div>
<style>
div {
display: flex;
gap: 0.2em;
align-items: center;
}
.editMode {
display: none;
hidden: true;
}
</style>

17
src/components/Icon.astro Normal file
View file

@ -0,0 +1,17 @@
---
const { chorecoin, gem } = Astro.props;
---
<img src={
chorecoin
? "/static/chorecoin.svg"
: gem
? "/static/gem.svg"
: undefined
} />
<style>
img {
height: 1cap;
}
</style>

45
src/components/Tab.astro Normal file
View file

@ -0,0 +1,45 @@
---
let { path } = Astro.props;
if (path.startsWith('/')) path = path.slice(1);
const activePath = Astro.url.pathname.slice(1);
const active = activePath === path;
---
<div class="tab">
<a href={'/' + path} class={active ? 'active' : 'inactive'}>
<slot />
<sup class="badge"
hx-trigger={active ? 'load, questComplete from:body' : 'load'}
hx-get={`/page/incomplete_count?route=${path}`}
hx-target="this"
hx-swap="innerText"
>
?
</sup>
</a>
</div>
<style>
.tab {
position: relative;
}
a {
color: black;
text-decoration: none;
}
.tab:has(a.active) {
border-bottom: 2px solid black;
}
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: small;
margin-left: -0.5em;
}
</style>

51
src/components/tabs.astro Normal file
View file

@ -0,0 +1,51 @@
---
import Tab from './Tab.astro'
import { Page } from '../lib/Page';
const path = Astro.url.pathname;
const pageData = Page.db.query('select route, name from pages').values();
---
<nav>
{ pageData.map(([path, name]) => <Tab {...{path}}>{name}</Tab>) }
<form class="editMode" hx-on::after-request="if(event.detail.successful) this.reset()">
<input name="name" placeholder="Page name" />
<input name="path" placeholder="/path" />
<input name="resetSchedule" placeholder="daily" />
<button
hx-put="/event/page/create"
hx-target="closest form"
hx-swap="beforebegin"
>
Create
</button>
</form>
</nav>
<style>
nav {
display: flex;
flex-direction: column;
gap: 1rem;
}
nav .tab {
height: fit-content;
}
nav a {
color: black;
text-decoration: none;
}
.tab:has(a.active) {
border-bottom: 2px solid black;
}
form.editMode {
display: none;
hidden: true;
width: 6em;
flex-direction: column;
gap: 0.5em;
margin-top: 1em;
}
</style>

182
src/layouts/Layout.astro Normal file
View file

@ -0,0 +1,182 @@
---
import Bank from '../pages/bank.astro';
import Vertitabs from '../components/tabs.astro';
const { tabs } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<script src="https://unpkg.com/htmx.org@2" is:inline></script>
<script src="https://unpkg.com/luxon@3" is:inline></script>
<title>Gachore</title>
</head>
<body>
<div class="topbar">
<Bank />
<a href={ tabs ? "/gacha" : "/" }>{`To ${ tabs ? "Gacha" : "Quests" }`}</a>
<button id="edit_mode">Edit Mode</button>
</div>
<div class="row">
{ tabs ? <Vertitabs /> : null }
<main>
<slot />
</main>
</div>
</body>
</html>
<script>
window.sessionStorage.removeItem("gachore:mode");
const button = document.getElementById("edit_mode");
const setVisibility = () => {
if (window.sessionStorage?.getItem("gachore:mode") === "edit") {
document.querySelectorAll('.editMode').forEach(el => {
el.style.display = 'flex';
el.style.hidden = false;
});
document.querySelectorAll('.viewMode').forEach(el => {
el.style.display = 'none';
el.style.hidden = true;
});
} else {
document.querySelectorAll('.editMode').forEach(el => {
el.style.display = 'none';
el.style.hidden = true;
});
document.querySelectorAll('.viewMode').forEach(el => {
el.style.removeProperty('display');
el.style.hidden = false;
});
}
};
button?.addEventListener('click', (evt) => {
evt.preventDefault();
if (window.sessionStorage?.getItem("gachore:mode") === "edit") {
button.innerText = "Edit Mode"
window.sessionStorage.removeItem("gachore:mode");
} else {
button.innerText = "View Mode"
window.sessionStorage.setItem("gachore:mode", "edit");
}
setVisibility();
});
window.addEventListener('htmx:afterRequest', () => {
setVisibility();
});
</script>
<style>
#edit_mode {
font-size: 80%;
}
.topbar {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
gap: 1em;
a {
color: black;
}
}
.row {
display: flex;
flex-direction: row;
height:100%;
gap: 2rem;
}
main {
display: flex;
flex-direction: column;
flex-grow: 1;
gap: 1rem;
}
</style>
<style is:global>
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
}
@media (prefers-reduced-motion: no-preference) {
html {
interpolate-size: allow-keywords;
}
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
margin: 0 auto;
height: 100vh;
display: flex;
flex-direction: column;
padding: 1rem;
width: 100%;
max-width: 800px;
font-size: 24px;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
p {
text-wrap: pretty;
}
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
text-align: right;
}
.editMode {
display: none;
hidden: true;
}
.editMode input, input.editMode {
min-width: 1.5em;
}
input {
border: none;
border-bottom: 1px solid gray;
margin: 0;
padding-left: 0;
padding-right: 0;
&.coins-reward {
width: 1.5em;
}
}
</style>

182
src/lib/Model.ts Normal file
View file

@ -0,0 +1,182 @@
import "reflect-metadata";
import { Database } from "bun:sqlite";
const fieldsKey = Symbol.for("custom:fields");
const tableKey = Symbol.for("custom:table");
type Sqlable = null | number | string | boolean | bigint;
export function column<This extends Object>(columnName?: string) {
return function (instance: This, propertyName: string) {
const col = columnName ?? propertyName;
const columns = Reflect.getMetadata(fieldsKey, instance.constructor) ?? {};
columns[propertyName] = col;
Reflect.defineMetadata(fieldsKey, columns, instance.constructor);
};
}
export function table(tableName: string) {
return Reflect.metadata(tableKey, tableName);
}
export abstract class Model {
private static _db: Database;
public static get db() {
return (Model._db ??= new Database("file.sqlite3"));
}
public loaded = false;
public constructor(public readonly id: DbId) {}
load() {
const table = Reflect.getMetadata(tableKey, this.constructor);
const fields = Object.entries(
Reflect.getMetadata(fieldsKey, this.constructor),
);
const columns = fields.map(([_, colname]) => colname);
const results = Model.db
.prepare(`select ${columns.join(",")} from ${table} where id=?`)
.values(this.id);
if (results.length === 0) throw new Error("invalid id");
fields.forEach(([property], idx) => {
// @ts-ignore
this[property] = results[0][idx];
});
this.loaded = true;
}
save() {
const table = Reflect.getMetadata(tableKey, this.constructor);
const fields = Object.entries(
Reflect.getMetadata(fieldsKey, this.constructor),
);
const columns = fields.map(([_, colname]) => colname);
Model.db
.prepare(
`update ${table} set ${columns.map((c) => `${c}=?`).join(",")} where id=?`,
)
.run(
...fields.map(
([property]) => this[property as keyof typeof this] as Sqlable,
),
this.id,
);
return this;
}
static builder(Ctor: Function, obj: { [key: string]: Sqlable }) {
const table = Reflect.getMetadata(tableKey, Ctor);
const fields = Object.entries(Reflect.getMetadata(fieldsKey, Ctor));
const columns = fields.map(([_, colname]) => colname);
return {
...obj,
save() {
const { lastInsertRowid } = Model.db
.prepare(
`insert into ${table}(${columns.join(",")}) values (${columns.map((_) => "?").join(",")})`,
)
.run(
...fields.map(
([property]) => obj[property as keyof typeof obj] as Sqlable,
),
);
return lastInsertRowid;
},
};
}
static load(_id: DbId) {
throw new Error("only implemented in concrete subclasses");
}
static requiredFields: {} | null;
}
export const loadInterceptor = {
get<T extends Model>(target: T, property: string) {
if (property === "id") return target.id;
if (!target.loaded) target.load();
return target[property as keyof T];
},
set<T extends Model>(target: T, property: string, value: T[keyof T]) {
if (!target.loaded) target.load();
target[property as keyof T] = value;
return true;
},
};
export function create<
T extends Model,
const U extends { [key: string]: Sqlable },
>(
Ctor: (new (id: DbId) => T) & { requiredFields: U | null },
obj: Exclude<typeof Ctor.requiredFields, null>,
): T {
const id = Model.builder(Ctor, obj).save();
return new Proxy<T>(new Ctor(id), loadInterceptor);
}
export function findMany<
T extends Model,
const U extends { [key: string]: Sqlable },
>(
Ctor: (new (id: DbId) => T) & { requiredFields: U | null },
obj: Partial<Exclude<typeof Ctor.requiredFields, null>> = {},
): T[] {
const table = Reflect.getMetadata(tableKey, Ctor);
const fields = Reflect.getMetadata(fieldsKey, Ctor);
const properties = Object.keys(obj)
.filter((key) => key in fields)
.filter((key) => obj[key] !== undefined);
const columns = properties.map((prop) => fields[prop]);
const values = properties.map((prop) => obj[prop] as Sqlable);
const whereClause =
properties.length === 0
? ""
: ` where ${columns.map((c) => `${c}=?`).join(" and ")}`;
const ids = Model.db
.prepare(`select id from ${table}${whereClause}`)
.values(...values);
return ids.map(([id]) => new Proxy<T>(new Ctor(id as DbId), loadInterceptor));
}
export function find<
T extends Model,
const U extends { [key: string]: Sqlable },
>(
Ctor: (new (id: DbId) => T) & { requiredFields: U | null },
obj: Partial<Exclude<typeof Ctor.requiredFields, null>>,
): T {
const matches = findMany(Ctor, obj);
if (matches.length !== 1) {
throw new Error("expected exactly one match; found " + matches.length);
}
return matches[0];
}
export function findOrCreate<
T extends Model,
const U extends { [key: string]: Sqlable },
>(
Ctor: (new (id: DbId) => T) & { requiredFields: U | null },
findObj: Partial<Exclude<typeof Ctor.requiredFields, null>>,
addlCreateObj: Partial<Exclude<typeof Ctor.requiredFields, null>>,
): T {
try {
return find(Ctor, findObj);
} catch (e: any) {
if (!e.message.startsWith("expected exactly")) throw e;
}
const fullObj = { ...findObj, ...addlCreateObj };
return create(Ctor, fullObj as Exclude<typeof Ctor.requiredFields, null>);
}

18
src/lib/Page.ts Normal file
View file

@ -0,0 +1,18 @@
import { Model, column, table, loadInterceptor } from "@/lib/Model";
@table("pages")
export class Page extends Model {
@column() public name!: string;
@column() public route!: string;
@column("reset_schedule") public resetSchedule!: string;
static load(id: DbId): Page {
return new Proxy<Page>(new Page(id), loadInterceptor);
}
static requiredFields: {
name: string;
route: string;
resetSchedule: string;
} | null = null;
}

59
src/lib/Quest.spec.ts Normal file
View file

@ -0,0 +1,59 @@
import { describe, test, expect } from "bun:test";
import { Database } from "bun:sqlite";
import { squish } from "./tags";
import { Model } from "./Model";
import { Quest } from "./Quest";
import { Questline } from "./Questline";
describe("Quest", () => {
test("can create and save", () => {
Model["_db"] = new Database(":memory:");
Model.db.exec("PRAGMA journal_mode = WAL;");
Model.db.exec("PRAGMA foreign_keys;");
Model.db
.prepare(
squish`
create table if not exists questlines(
id integer primary key autoincrement,
name text
)
`,
)
.run();
Model.db
.prepare(
squish`
create table if not exists quests(
id integer primary key autoincrement,
coins_reward number,
reward text,
questline_id integer,
completed bool,
claimed bool,
foreign key(questline_id) references questlines(id)
)
`,
)
.run();
Model.create(Questline, { name: "Dailies" });
const quest = Model.create(Quest, {
coinsReward: 10,
questlineId: 1,
completed: false,
claimed: false,
});
const sameQuest = Model.find(Quest, { questlineId: 1 });
sameQuest.coinsReward = 20;
sameQuest.save();
quest.load();
expect(quest.coinsReward).toEqual(20);
});
});

41
src/lib/Quest.ts Normal file
View file

@ -0,0 +1,41 @@
import { type Slug, Slugs } from "@/lib/slug";
import { Model, table, column, loadInterceptor } from "@/lib/Model";
import { Questline } from "@/lib/Questline";
@table("quests")
export class Quest extends Model {
@column() public name!: string;
@column() public completed!: boolean;
@column() public claimed!: boolean;
@column("sort_order") public sortOrder: number | undefined;
@column("coins_reward") public coinsReward!: number;
@column("questline_id") public questlineId!: DbId;
public readonly slug: Slug;
public constructor(id: DbId) {
super(id);
this.slug = Slugs.encode(this.id);
}
public get questline() {
return new Questline(this.questlineId);
}
///
static load(id: DbId): Quest {
return new Proxy<Quest>(new Quest(id), loadInterceptor);
}
static requiredFields: {
name: string;
coinsReward: number;
questlineId: DbId;
completed: boolean;
claimed: boolean;
} | null = null;
static build(obj: Exclude<typeof Quest.requiredFields, null>) {
return Model.builder(this, obj);
}
}

20
src/lib/Questline.ts Normal file
View file

@ -0,0 +1,20 @@
import { Model, column, table, loadInterceptor } from "@/lib/Model";
@table("questlines")
export class Questline extends Model {
@column() public name!: string;
@column() public claimed!: boolean;
@column("coins_reward") public coinsReward!: number;
@column("page_id") public pageId!: number;
static load(id: DbId): Questline {
return new Proxy<Questline>(new Questline(id), loadInterceptor);
}
static requiredFields: {
name: string;
claimed: boolean;
coinsReward: number;
pageId: DbId;
} | null = null;
}

5
src/lib/Reward.ts Normal file
View file

@ -0,0 +1,5 @@
export const RewardState = {
deleted: 0,
inactive: 1,
active: 2,
};

6
src/lib/auth.ts Normal file
View file

@ -0,0 +1,6 @@
import { betterAuth } from "better-auth";
import { Database } from "bun:sqlite";
export const auth = betterAuth({
database: new Database("./auth.db"),
})

1
src/lib/common.d.ts vendored Normal file
View file

@ -0,0 +1 @@
type DbId = number | bigint;

169
src/lib/db_init.ts Normal file
View file

@ -0,0 +1,169 @@
import { Model, findOrCreate } from "./Model";
import { Questline } from "./Questline";
import { Quest } from "./Quest";
import { Page } from "./Page";
import { squish } from "./tags";
export default {
name: "db init",
hooks: {
"astro:server:setup": () => {
Model.db.exec("PRAGMA journal_mode = WAL;");
Model.db.exec("PRAGMA foreign_keys;");
const sql = (str: string) => Model.db.prepare(str).run();
sql(squish`
create table if not exists pages(
id integer primary key autoincrement,
name text unique,
route text unique,
reset_schedule text
)
`);
sql(squish`
create table if not exists questlines(
id integer primary key autoincrement,
coins_reward integer,
claimed bool,
name text unique,
page_id integer,
foreign key(page_id) references page(id)
)
`);
sql(squish`
create table if not exists quests(
id integer primary key autoincrement,
name text,
coins_reward integer,
questline_id integer,
completed bool,
claimed bool,
sort_order integer,
foreign key(questline_id) references questlines(id)
unique(name, questline_id)
)
`);
sql(squish`
create table if not exists events(
id integer primary key autoincrement,
record_time datetime not null default current_timestamp,
kind text,
quest_id integer,
questline_id integer,
coins_claimed integer,
coins_spent integer,
gems_claimed integer,
gems_spent integer,
reward_id integer,
foreign key(quest_id) references quests(id)
foreign key(questline_id) references questlines(id)
foreign key(reward_id) references rewards(id)
)
`);
sql(squish`
create table if not exists rewards(
id integer primary key autoincrement,
state integer not null default 2,
name text,
link text,
cents integer,
gems_cost integer,
rarity real,
chance real,
sort_order integer
);
`);
sql(squish`
create table if not exists inventory(
id integer primary key autoincrement,
reward_id integer,
state text,
foreign key(reward_id) references rewards(id)
)
`);
sql(squish`
create trigger if not exists insert_reward_chances after insert on rewards
begin
update rewards set gems_cost = cents * 2 where id = NEW.id;
update rewards set rarity = 100 / pow(gems_cost / 100, 2) where id = NEW.id;
update rewards set chance = rarity / (select sum(rarity) from rewards);
end
`);
sql(squish`
create trigger if not exists update_reward_chances after update of cents on rewards
begin
update rewards set gems_cost = cents * 2 where id = NEW.id;
update rewards set rarity = 100 / pow(gems_cost / 100, 2) where id = NEW.id;
update rewards set chance = rarity / (select sum(rarity) from rewards);
end
`);
sql(squish`
create trigger if not exists pull_rewards_to_inventory after update of reward_id on events
when NEW.kind = 'gacha_pull'
begin
insert into inventory (reward_id) values (NEW.reward_id);
end
`);
let dailyPageId = findOrCreate(Page, { name: "Daily", route: "" }, {}).id;
let questlineId = findOrCreate(
Questline,
{ name: "Mornings", pageId: dailyPageId },
{ coinsReward: 20, claimed: false },
).id;
findOrCreate(
Quest,
{ name: "Bed", questlineId },
{ coinsReward: 10, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Brush", questlineId },
{ coinsReward: 10, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Laundry", questlineId },
{ coinsReward: 15, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Outside", questlineId },
{ coinsReward: 20, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Yoga", questlineId },
{ coinsReward: 25, completed: false, claimed: false },
);
questlineId = findOrCreate(
Questline,
{ name: "Dailies", pageId: dailyPageId },
{ coinsReward: 20, claimed: false },
).id;
findOrCreate(
Quest,
{ name: "Cleandish", questlineId },
{ coinsReward: 15, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Floss", questlineId },
{ coinsReward: 10, completed: false, claimed: false },
);
findOrCreate(
Quest,
{ name: "Read-a-page", questlineId },
{ coinsReward: 5, completed: false, claimed: false },
);
findOrCreate(Page, { name: "Main Room", route: "main" }, {});
},
},
};

7
src/lib/gacha_pull.ts Normal file
View file

@ -0,0 +1,7 @@
export const pullChances = [
{ chance: 0.4030, gems: 25, cdf: 0.4030, name: 'common' },
{ chance: 0.2970, gems: 80, cdf: 0.7000, name: 'rare' },
{ chance: 0.1775, gems: 135, cdf: 0.8775, name: 'epic' },
{ chance: 0.0725, gems: 280, cdf: 0.9500, name: 'legendary' },
{ chance: 0.0500, cdf: 1.0000, name: 'reward' },
] as const;

39
src/lib/slug.ts Normal file
View file

@ -0,0 +1,39 @@
import Sqids from "sqids";
export type Slug = string & { readonly __tag: unique symbol };
export class Slugs {
private static instance: Slugs;
private sqids!: Sqids;
private constructor() {
if (Slugs.instance) return Slugs.instance;
Slugs.instance = this;
this.sqids = new Sqids({
alphabet: "dbnixSPYJNy5hvsqCWIHwEKTFutV6r4Xa32okL8RQUj7Am9DcpgfZezMBG",
});
}
static encode(num: number | bigint): Slug {
const sqids = new Slugs().sqids;
const thirtyTwoBitMax = BigInt(0xffffffff);
if (typeof num === "bigint" && num > thirtyTwoBitMax) {
const arr = [];
while (num > 0) {
arr.push(Number(num & thirtyTwoBitMax));
num >>= 32n;
}
return sqids.encode(arr) as Slug;
} else {
return sqids.encode([Number(num)]) as Slug;
}
}
static decode(slug: Slug): number | bigint {
const ns = new Slugs().sqids.decode(slug);
if (ns.length === 1) return ns[0];
return ns.reduceRight((big, each) => (big << 32n) + BigInt(each), 0n);
}
}

17
src/lib/tags.ts Normal file
View file

@ -0,0 +1,17 @@
import unraw from "unraw";
export const squish = (strings: TemplateStringsArray, ...values: string[]) => {
const firstIndent = strings.raw[0].match(/\n(\s*)/)?.[1];
return String.raw(
{
raw: strings.raw.map((raw) => {
// remove indent up to that of the first line
if (firstIndent) raw = raw.replaceAll(`\n${firstIndent}`, "\n");
// collapse newlines not immediately surrounded by more whitespace
return unraw(raw.replace(/(?<=\S)\n(?=\S)/g, " "));
}),
},
...values,
).trim();
};

95
src/pages/QuestRow.astro Normal file
View file

@ -0,0 +1,95 @@
---
export const partial = true;
export const prerender = false;
import { Quest } from '../lib/Quest';
import Currency from '../components/Currency.astro';
const { id } = Astro.props;
const quest = Quest.load(id);
---
<div class={quest.claimed ? "quest claimed" : "quest"} hx-target="this" hx-swap="outerHTML">
<div class="editMode buttons" hx-target="closest fieldset">
<button hx-post={`/event/quest/reorder?up&id=${id}`}>^</button>
<button hx-post={`/event/quest/delete?id=${id}`}>x</button>
<button hx-post={`/event/quest/reorder?down&id=${id}`}>v</button>
</div>
<input type="checkbox"
id={`quest-${id}-completed`}
class="viewMode"
checked={quest.completed}
disabled={quest.claimed}
hx-post={`/event/quest/complete?id=${id}`}
hx-disabled-elt="this"
/>
<label for={`quest-${id}-completed`} class="name viewMode">{quest.name}</label>
<input class="name editMode" name="name" value={quest.name}
hx-post=`/event/quest/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous"
hx-swap="textContent"
/>
<Currency class="coins-reward viewMode" chorecoin>{quest.coinsReward}</Currency>
<Currency class="coins-reward editMode" chorecoin>
<input class="coins-reward" name="coinsReward" value={quest.coinsReward}
type="number"
hx-post=`/event/quest/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous span"
hx-swap="textContent"
/>
</Currency>
<button
disabled={!quest.completed || quest.claimed}
hx-post={`/event/quest/claim?id=${id}`}
hx-disabled-elt="this"
class="claim viewMode"
>
Claim{quest.claimed ? "ed!" : ""}
</button>
<button disabled class="claim editMode">Claim{quest.claimed ? "ed!" : ""}</button>
</div>
<style>
.buttons.editMode {
flex-direction: column;
gap: 0;
font-size: x-small;
opacity: 100%;
button {
margin: 0 0 0 -1em;
}
}
.quest {
border: 1px solid black;
border-radius: 5px;
padding: 0 1rem;
gap: 0.5em;
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
.name {
flex-grow: 1;
flex-basis: 20px;
}
}
.quest.claimed {
color: rgba(0, 0, 0, 0.3);
img { filter: invert(70%); }
order: 1;
}
button.claim {
margin: 1rem 0;
}
</style>

View file

@ -0,0 +1,76 @@
---
export const prerender = false;
const pageRoute = Astro.params.pageRoute ?? '';
import Layout from '../layouts/Layout.astro';
import QuestlineDisp from './questline/[id].astro';
import ResetTimer from './page/reset_timer.astro';
import ClaimAllButton from './page/claim_all_button.astro';
import ResetButton from './page/reset_button.astro';
import { Questline } from '../lib/Questline';
let ok = true;
const pageId = Questline.db.query('select id from pages where route = ?').values(pageRoute)[0]?.[0];
let questlineIds: DbId[] = [];
if (pageId) {
questlineIds = Questline.db.query('select id from questlines where page_id = ?').values(pageId);
} else {
ok = false;
Astro.response.status = 404;
Astro.response.statusText = `No page with route '${pageRoute}'`;
}
---
<Layout tabs>
{ ok ? null : `${Astro.response.status}: ${Astro.response.statusText}` }
{ questlineIds.length ? <div id="reset">
<span>
Reset in <ResetTimer page={pageId} />
</span>
<ClaimAllButton page={pageId} />
<ResetButton page={pageId} />
</div> : null }
{ questlineIds.map(id => <QuestlineDisp {...{ id }} />) }
<form class="editMode addQuestLine" hx-on::after-request="if(event.detail.successful) this.reset()">
<input name="name" placeholder="Questline" />
<input name="reward" placeholder="Coins" width="3" />
<button
hx-put=`/event/questline/create?page=${pageId}`
hx-target="closest form"
hx-swap="beforebegin"
>Create</button>
</form>
</Layout>
<style>
.editMode {
display: none;
}
#reset {
margin-top: 1em;
font-size: 80%;
display: flex;
width: 100%;
gap: 0.8em;
& span {
flex-grow: 1;
}
}
form.editMode {
display: none;
hidden: true;
gap: 0.5em;
input[name="name"] {
flex-grow: 1;
}
input[name="reward"] {
width: 4em;
}
}
</style>

147
src/pages/bank.astro Normal file
View file

@ -0,0 +1,147 @@
---
export const prerender = false;
export const partial = true;
import Currency from '../components/Currency.astro';
import Icon from '../components/Icon.astro';
import { Model } from '../lib/Model';
import { squish } from '../lib/tags';
const result = Model.db.query(squish`
select
ifnull(sum(coins_claimed), 0) - ifnull(sum(coins_spent), 0),
ifnull(sum(gems_claimed), 0) - ifnull(sum(gems_spent), 0)
from events
`).values();
const chorecoins = result[0][0] ?? 0;
const gems = result[0][1] ?? 0;
const transactions = Model.db.query(squish`
select coins_claimed, gems_claimed, coins_spent, gems_spent, record_time, kind, qs.name as quest, ql.name as questline
from events ev
full outer join questlines ql on ql.id = ev.questline_id
full outer join quests qs on qs.id = ev.quest_id
where (
ev.coins_claimed > 0
or ev.gems_claimed > 0
or ev.coins_spent > 0
or ev.gems_spent > 0
)
order by record_time desc
`).all();
const isoDate = (d: Date) => d.toISOString().split('T')[0];
---
<div id="bank" hx-get="/bank" hx-trigger="bankUpdate from:body" data-micromodal-trigger="earnlog-modal">
<button id="earnlog-shower">
<Currency chorecoin>{chorecoins}</Currency>
<Currency gem>{gems}</Currency>
</button>
<dialog id="earnlog">
<header>
<h2 id="earnlog-title">
Transactions
</h2>
<form method="dialog">
<button aria-label="Close modal"></button>
</form>
</header>
<div class="content">
<div>Date</div>
<div>Event</div>
<div class="span2"><Icon chorecoin /></div>
<div class="span2"><Icon gem /></div>
{transactions.map(({ record_time, kind, quest, questline, ...event }) => (
<>
<div>{ isoDate(new Date(record_time)) }</div>
<div>{
kind === "claim_quest" ? `Claimed ${quest}` :
kind === "claim_questline" ? `Completed ${questline}` :
kind
}</div>
<div class="debit">{ event.coins_spent ?? '' }</div>
<div class="credit">{ event.coins_claimed ?? '' }</div>
<div class="debit">{ event.gems_spent ?? '' }</div>
<div class="credit">{ event.gems_claimed ?? '' }</div>
</>
))}
</div>
</dialog>
</div>
<script>
const earnlog = document.getElementById("earnlog");
document.getElementById("earnlog-shower").addEventListener("click", () => {
earnlog.showModal();
});
earnlog.addEventListener("click", (evt) => {
if (evt.target === earnlog)
earnlog.close();
});
</script>
<style>
#earnlog-shower {
display: flex;
flex-direction: row;
gap: 2em;
background: transparent;
border: 0;
cursor: pointer;
}
dialog {
margin: auto;
max-height: 85vh;
overflow-y: auto;
}
dialog header {
display: flex;
justify-content: space-between;
align-items: center;
}
dialog header button {
background: transparent;
border: 0;
cursor: pointer;
}
dialog header button:before { content: "\2715"; }
dialog .content {
--gap: 1em;
width: 100%;
display: grid;
gap: 0;
grid-template-columns: 1fr 2fr repeat(4, 5ch);
border-top: 1px solid gray;
border-left: 1px solid gray;
& > * {
border-right: 1px solid gray;
border-bottom: 1px solid gray;
padding: 0 calc(var(--gap) / 2);
}
.span2 {
grid-column: span 2;
display: flex;
align-items: center;
justify-content: center;
}
.debit, .credit {
text-align: right;
}
.span2:nth-child(3),
.credit:nth-child(6n + 2) {
border-right: 5px double gray;
}
}
</style>

View file

@ -0,0 +1,53 @@
---
export const prerender = false;
export const partial = true;
import ClaimAllButton from '../../page/claim_all_button.astro';
import { Page } from '../../../lib/Page';
import { squish } from '../../../lib/tags';
const pageId = Astro.url.searchParams.get('page');
const questClaims = Page.db.query(squish`
update quests set claimed = true where id in (
select qs.id from quests qs
join questlines ql on ql.id = qs.questline_id
join pages ps on ps.id = ql.page_id
where qs.completed = true
and qs.claimed = false
and ps.id = ?
)
returning id, coins_reward;
`).values(pageId);
const claimQuestCoins = Page.db.query(squish`
insert into events(kind, quest_id, coins_claimed)
values ('claim_quest', ?, ?)
`);
Page.db.transaction(claims => {
for(const [id, coins] of claims) claimQuestCoins.run(id, coins)
})(questClaims);
const questlineClaims = Page.db.query(squish`
update questlines set claimed = true where id in (
select ql.id from questlines ql
join pages ps on ps.id = ql.page_id
where ps.id = ?
and ql.claimed = false
and (select min(completed) from quests qs where qs.questline_id = ql.id) = 1
)
returning id, coins_reward
`).values(pageId);
const claimQuestlineCoins = Page.db.query(squish`
insert into events(kind, questline_id, coins_claimed)
values ('claim_questline', ?, ?)
`);
Page.db.transaction(claims => {
for(const [id, coins] of claims) claimQuestlineCoins.run(id, coins)
})(questlineClaims);
Astro.response.headers.set('HX-Trigger', 'claimedAll, questClaimed, bankUpdate');
---
<ClaimAllButton page={pageId} />

View file

@ -0,0 +1,33 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import Tab from '../../../components/Tab.astro';
const form = await Astro.request.formData();
const name = form.get("name") as string;
const path = form.get("path") as string;
const reset = form.get("resetSchedule") as string;
let ok = true;
if (name.length < 1) {
ok = false;
Astro.response.status = 400;
} else {
try {
Quest.db.query(squish`
insert into pages (name, route, reset_schedule)
values (?1, ?2, ?3)
`).run(name, path, reset);
} catch(e) {
ok = false;
console.log(`Following error is for name [${name}] path [${path}]`);
console.error(e);
Astro.response.status=400;
}
}
---
{ ok && <Tab path={path}>{name}</Tab> }

View file

@ -0,0 +1,34 @@
---
export const prerender = false;
export const partial = true;
import ResetButton from '../../page/reset_button.astro';
import { Page } from '../../../lib/Page';
import { squish } from '../../../lib/tags';
const pageId = Astro.url.searchParams.get('page');
Page.db.query(squish`
update quests set completed = false, claimed = false where id in (
select qs.id from quests qs
join questlines ql on ql.id = qs.questline_id
join pages ps on ps.id = ql.page_id
where qs.completed = true
and ps.id = ?
)
`).run(pageId);
Page.db.query(squish`
update questlines set claimed = false where id in (
select ql.id from questlines ql
join pages ps on ps.id = ql.page_id
where ql.claimed = true
and ps.id = ?
)
`).run(pageId);
Astro.response.headers.set('HX-Trigger', 'reset');
---
<ResetButton page={pageId} />

View file

@ -0,0 +1,66 @@
---
export const partial = true;
export const prerender = false;
import Currency from '../../components/Currency.astro';
import { RewardState } from '../../lib/Reward';
import { pullChances } from '../../lib/gacha_pull';
import { Model } from '../../lib/Model';
import { squish } from '../../lib/tags';
const rand = Math.random();
const pulled = pullChances.find(which => which.cdf > rand);
let reward = null;
console.log({ pulled });
if (pulled.gems) {
Model.db.query(squish`
insert into events (kind, coins_spent, gems_claimed)
values ('gacha_pull', 100, ?)
`).run(pulled.gems)
} else {
const rewards = Model.db.query(squish`
select id, name, chance from rewards where state > ? order by sort_order
`).all(RewardState.inactive);
let rand = Math.random();
// in case we get floating-point'd, change chance of the last reward in the list to be
// 1.0. The cdf at that point would be within epsilon, but technically possible that
// it's just on the wrong side of epsilon away from rand
rewards[rewards.length-1].chance = 1;
for (const { id, name, chance } of rewards) {
if (chance > rand) {
// won
reward = { kind: 'reward', id, name, chance };
break;
} else {
rand -= chance;
}
}
console.log({ reward });
Model.db.query(squish`
insert into events (kind, coins_spent, reward_id)
values ('gacha_pull', 100, ?)
`).run(reward.id);
}
Astro.response.headers.set('HX-Trigger', 'bankUpdate');
---
<>
<header>
<h3>Result</h3>
<form method="dialog">
<button aria-label="Close modal"></button>
</form>
</header>
<div class={`rarity ${pulled.name}`}>
{ pulled.gems ? <Currency gem>{pulled.gems}</Currency> : reward.name }
</div>
</>

View file

@ -0,0 +1,26 @@
---
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import QuestRow from '../../QuestRow.astro';
export const prerender = false;
export const partial = true;
const id = Astro.url.searchParams.get('id') || '';
const quest = Quest.load(id);
if (!quest.claimed) {
quest.claimed = true;
quest.save();
Quest.db.prepare(squish`
insert into events(
kind, quest_id, coins_claimed
) values ("claim_quest", ?, ?)
`).values(id, quest.coinsReward);
Astro.response.headers.set('HX-Trigger', 'questClaimed, bankUpdate');
}
---
<QuestRow id={id} />

View file

@ -0,0 +1,17 @@
---
import QuestRow from '../../QuestRow.astro';
import { Quest } from '../../../lib/Quest';
export const prerender = false;
export const partial = true;
const id = Astro.url.searchParams.get('id') || '';
const quest = Quest.load(id);
quest.completed = !quest.completed;
quest.save();
Astro.response.headers.set('HX-Trigger', `questComplete, questComplete-ql${quest.questlineId}`);
---
<QuestRow id={id} />

View file

@ -0,0 +1,34 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import QuestlineDisp from '../../questline/[id].astro';
const questlineId = Astro.url.searchParams.get('questline') || '';
const form = await Astro.request.formData();
const name = form.get("name") as string;
const reward = form.get("reward") as string;
const coins = Number.parseInt(reward, 10);
let ok = true;
if (!questlineId || name.length < 1 || reward.length < 1 || Number.isNaN(coins)) {
ok = false;
Astro.response.status = 400;
} else {
try {
Quest.db.query(squish`
insert into quests (name, coins_reward, questline_id, sort_order, completed, claimed)
values (?1, ?2, ?3, (select 1+max(sort_order) from quests where questline_id = ?3), false, false)
`).run(name, coins, questlineId);
} catch(e) {
ok = false;
console.log(`Following error for name [${name}] coins [${coins}] qlid [${questlineId}]`);
console.error(e);
Astro.response.status=400;
}
}
---
{ ok && <QuestlineDisp id={questlineId} /> }

View file

@ -0,0 +1,22 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import QuestlineDisp from '../../questline/[id].astro';
const id = Astro.url.searchParams.get('id') || '';
const quest = Quest.load(id);
const questline = quest.questline;
// TODO soft delete so logs don't break
Quest.db
.query(squish`
delete from quests
where id = ?
`).values(id)
---
<QuestlineDisp id={questline.id}>

View file

@ -0,0 +1,20 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
const id = Astro.url.searchParams.get('id');
const form = await Astro.request.formData();
const name = form.get("name") as string;
const coinsReward = form.get("coinsReward") as string;
if (name) {
Quest.db.query("update quests set name=? where id=?").values(name, id)
} else if (coinsReward) {
Quest.db.query("update quests set coins_reward=? where id=?").values(coinsReward, id)
}
---
{name ? name : coinsReward}

View file

@ -0,0 +1,51 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import QuestlineDisp from '../../questline/[id].astro';
const up = Astro.url.searchParams.has('up');
const down = Astro.url.searchParams.has('down');
const id = Astro.url.searchParams.get('id') || '';
const quest = Quest.load(id);
const questline = quest.questline;
const sortOrders = Quest.db
.query(squish`
update quests
set sort_order = subq.questline_order
from (
select *, row_number() over(order by sort_order) as questline_order
from quests where questline_id=? order by sort_order
) subq
where quests.id = subq.id
returning sort_order
`).values(questline.id)
const maxSortOrder = sortOrders[sortOrders.length - 1][0];
quest.load();
const canReorder = up
? quest.sortOrder > 1
: down
? quest.sortOrder < maxSortOrder
: false;
if (canReorder) {
Quest.db.query(squish`
update quests
set sort_order = sort_order ${ up ? '+' : '-' } 1
where questline_id=? and sort_order=?
`).values(questline.id, up ? quest.sortOrder - 1 : quest.sortOrder + 1);
Quest.db.query(squish`
update quests
set sort_order = sort_order ${ up ? '-' : '+' } 1
where id=?
`).values(id);
}
---
<QuestlineDisp id={questline.id}>

View file

@ -0,0 +1,24 @@
---
import { Questline } from '../../../lib/Questline';
import { squish } from '../../../lib/tags';
import QuestlineClaimRow from '../../questline/claim_row.astro';
export const prerender = false;
export const partial = true;
const id = Astro.url.searchParams.get('id') || '';
const questline = Questline.load(id);
questline.claimed = true;
questline.save();
Questline.db.prepare(squish`
insert into events(
kind, questline_id, coins_claimed
) values ("claim_questline", ?, ?)
`).values(id, questline.coinsReward);
Astro.response.headers.set('HX-Trigger', 'bankUpdate');
---
<QuestlineClaimRow id={id} />

View file

@ -0,0 +1,36 @@
---
export const prerender = false;
export const partial = true;
import { Quest } from '../../../lib/Quest';
import { squish } from '../../../lib/tags';
import QuestlineDisp from '../../questline/[id].astro';
const pageId = Astro.url.searchParams.get('page') || '';
const form = await Astro.request.formData();
const name = form.get("name") as string;
const reward = form.get("reward") as string;
const coins = Number.parseInt(reward, 10);
let ok = true;
let newQuestlineId = 0;
if (!pageId || name.length < 1 || reward.length < 1 || Number.isNaN(coins)) {
ok = false;
Astro.response.status = 400;
} else {
try {
newQuestlineId = Quest.db.query(squish`
insert into questlines (name, coins_reward, page_id, claimed)
values (?1, ?2, ?3, false)
`).run(name, coins, pageId)
.lastInsertRowid;
} catch(e) {
ok = false;
console.log(`Following error for name [${name}] coins [${coins}] pageid [${pageId}]`);
console.error(e);
Astro.response.status=400;
}
}
---
{ ok && <QuestlineDisp id={newQuestlineId} /> }

View file

@ -0,0 +1,20 @@
---
export const prerender = false;
export const partial = true;
import { Questline } from '../../../lib/Questline';
const id = Astro.url.searchParams.get('id');
const form = await Astro.request.formData();
const name = form.get("name") as string;
const coinsReward = form.get("coinsReward") as string;
if (name) {
Questline.db.query("update questlines set name=? where id=?").values(name, id)
} else if (coinsReward) {
Questline.db.query("update questlines set coins_reward=? where id=?").values(coinsReward, id)
}
---
{name ? name : coinsReward}

View file

@ -0,0 +1,34 @@
---
export const prerender = false;
export const partial = true;
import { Model } from '../../../lib/Model';
import { squish } from '../../../lib/tags';
const form = await Astro.request.formData();
const name = form.get("name") as string;
const link = (form.get("link") ?? '') as string;
const dollars = form.get("dollars") as string;
const cents = Math.floor(Number.parseFloat(dollars) * 100);
let ok = true;
if (name.length < 1 || Number.isNaN(cents)) {
ok = false;
Astro.response.status = 400;
} else {
try {
Model.db.query(squish`
insert into rewards (name, link, cents)
values (?1, ?2, ?3)
`).run(name, link, cents);
} catch(e) {
ok = false;
console.error(e);
Astro.response.status=400;
}
}
Astro.response.headers.set('HX-Trigger', 'rewardEdit');
---
{ ok ? '' : 'Error' }

View file

@ -0,0 +1,37 @@
---
export const prerender = false;
export const partial = true;
import { Model } from '../../../lib/Model';
const id = Astro.url.searchParams.get('id');
const form = await Astro.request.formData();
let name = form.get("name") as string;
let link = form.get("link") as string;
const dollars = form.get("dollars") as string;
let cents = undefined;
console.log({ name, link, dollars });
if (name !== null) {
[name, link] = Model.db.query(
"update rewards set name=? where id=? returning name, link"
).values(name, id)[0] as string[];
} else if (link !== null) {
[name, link] = Model.db.query(
"update rewards set link=? where id=? returning name, link"
).values(link === "" ? null : link, id)[0] as string[];
} else if (dollars !== null) {
cents = Math.floor(Number.parseFloat(dollars) * 100);
console.log({ cents });
Model.db.query("update rewards set cents=? where id=?").run(cents, id);
Astro.response.headers.set('HX-Trigger', 'rewardEdit');
}
---
{ link !== null ? <a class="viewMode" href={link}>{name}</a>
: name !== null ? <span class="viewMode">{name}</span>
: cents !== null ? (cents * 200)
: '?'
}

View file

@ -0,0 +1,50 @@
---
export const prerender = false;
export const partial = true;
import RewardList from '../../reward/list.astro';
import { Model } from '../../../lib/Model';
import { squish } from '../../../lib/tags';
const up = Astro.url.searchParams.has('up');
const down = Astro.url.searchParams.has('down');
const id = Number.parseInt(Astro.url.searchParams.get('id'), 10);
const refreshedSortOrders = Model.db
.query(squish`
update rewards
set sort_order = subq.reordered
from (
select *, row_number() over(order by sort_order) as reordered
from rewards
) subq
where rewards.id = subq.id
returning id, sort_order
`).all()
console.log({ refreshedSortOrders });
const maxSortOrder = refreshedSortOrders[refreshedSortOrders.length - 1].sort_order;
const currentSortOrder = refreshedSortOrders.find(each => each.id === id).sort_order;
const canReorder = up ?
currentSortOrder > 1 : down ?
currentSortOrder < maxSortOrder :
false;
if (canReorder) {
Model.db.query(squish`
update rewards
set sort_order = sort_order ${ up ? '+' : '-' } 1
where sort_order=?
`).values(up ? currentSortOrder - 1 : currentSortOrder + 1);
Model.db.query(squish`
update rewards
set sort_order = sort_order ${ up ? '-' : '+' } 1
where id=?
`).values(id);
}
---
<RewardList />

166
src/pages/gacha.astro Normal file
View file

@ -0,0 +1,166 @@
---
import Layout from '../layouts/Layout.astro';
import RewardList from './reward/list.astro';
import Currency from '../components/Currency.astro';
import { Model } from '../lib/Model';
import { squish } from '../lib/tags';
import { pullChances } from '../lib/gacha_pull';
const bankedCoins = Model.db.query(squish`
select ifnull(sum(coins_claimed), 0) - ifnull(sum(coins_spent), 0)
from events
`).values()?.[0]?.[0] as number;
const inventory = Model.db.query(squish`
select rd.id as id, rd.name as name, rd.gems_cost / 2 as sellFor from inventory inv
join rewards rd on inv.reward_id = rd.id
where inv.state is null;
`).all();
---
<Layout>
<div id="pull_chances">
{pullChances.map(({ chance, gems }) => (<div>
<span>{(chance*100).toPrecision(3)}%</span>
{ gems ? <Currency gem>{gems}</Currency> : <span>↓</span> }
</div>))}
<div>
<button disabled={bankedCoins < 100}
hx-get="/event/pull"
hx-target="#pull_results"
onclick="document.getElementById('pull_results').showModal()"
>
<span>Pull</span>
<Currency chorecoin class="cost">100</Currency>
</button>
</div>
{/*
<div>
<button disabled={bankedCoins < 1000}>
<span>Pull&nbsp;10</span>
<Currency chorecoin class="cost">1000</Currency>
</button>
</div>
*/}
</div>
<dialog id="pull_results">
</dialog>
<div id="inventory">
{ inventory.map(({ id, name, sellFor }) => (
<>
<div data-id={id}>{name}</div>
<div>{sellFor}</div>
</>
))}
</div>
<RewardList />
<form class="addReward editMode" hx-on::after-request="if(event.detail.successful) this.reset()">
<input name="name" placeholder="Reward" autofocus hx-on::after-request="if(event.detail.successful) this.focus()"/>
<input name="link" placeholder="link (optional)" />
<span class="dollars">
<input id="dollars" name="dollars" placeholder="0.00" type="number" step="0.01"/>
</span>
<button
hx-put=`/event/reward/create`
hx-target="closest form"
hx-swap="afterend"
>Create</button>
</form>
</Layout>
<style>
#pull_chances {
display: flex;
margin-top: 1em;
& div {
display: flex;
flex-direction: column;
padding-right: 1ch;
padding-left: 1ch;
border: 2px solid gray;
border-right: 0;
align-items: center;
justify-content: center;
&:first-child {
border-radius: 1em 0 0 1em;
}
&:last-child {
border-right: 2px solid gray;
border-radius: 0 1em 1em 0;
}
}
button {
display: flex;
flex-direction: column;
align-items: center;
.cost {
font-size: small;
}
}
}
form {
gap: 1em;
width: 100%;
}
input {
width: 15ch;
&[name="name"] {
flex-grow: 1;
}
}
.dollars {
display: inline-block;
position: relative;
font-family: monospace;
}
.dollars::before {
content: "$";
position: absolute;
left: 0.25em;
}
input[name="dollars"] {
min-width: 7ch;
width: 7ch;
}
dialog {
margin: auto;
header {
display: flex;
justify-content: space-between;
align-items: center;
button {
background: transparent;
border: 0;
cursor: pointer;
&:before { content: "\2715"; }
}
}
}
</style>
<style is:global>
.rarity {
aspect-ratio: 1/1;
display: flex;
align-items: center;
justify-content: center;
&.rare img { background-image: url('/static/rare.webp'); }
&.epic img { background-image: url('/static/epic.webp'); }
&.legendary img { background-image: url('/static/legendary.webp'); }
div {
flex-direction: column-reverse;
gap: 0;
img {
height: 80px;
background-size: contain;
}
}
}
</style>

6
src/pages/index.astro Normal file
View file

@ -0,0 +1,6 @@
---
import QuestlinePage from './[pageRoute].astro';
---
<QuestlinePage />

View file

@ -0,0 +1,28 @@
---
export const prerender = false;
export const partial = true;
import { Page } from '../../lib/Page';
import { squish } from '../../lib/tags';
const pageId = Astro.props.page ?? Astro.url.searchParams.get('page');
const canClaim = Page.db.query(squish`
select count(*) from pages p
join questlines ql on p.id = ql.page_id
join quests qs on ql.id = qs.questline_id
where qs.completed = true
`).values()?.[0]?.[0] > 0;
---
<div
hx-get={`/page/claim_all_button?page=${pageId}`}
hx-trigger="questComplete from:body"
>
<button
disabled={!canClaim}
hx-post={`/event/page/claim_all?page=${pageId}`}
hx-target="closest div"
hx-swap="outerHTML"
>
Claim all
</button>
</div>

View file

@ -0,0 +1,18 @@
---
export const partial = true;
export const prerender = false;
const pageRoute = Astro.url.searchParams.get('route') ?? '';
import { Page } from '../../lib/Page';
import { squish } from '../../lib/tags';
const count = Page.db.query(squish`
select count(*) from quests qs
join questlines ql on qs.questline_id = ql.id
join pages pg on ql.page_id = pg.id
where qs.completed = false
and pg.route = ?
`).values(pageRoute)?.[0]?.[0] ?? '?';
---
{count}

View file

@ -0,0 +1,28 @@
---
export const prerender = false;
export const partial = true;
import { Page } from '../../lib/Page';
import { squish } from '../../lib/tags';
const pageId = Astro.props.page ?? Astro.url.searchParams.get('page');
const canReset = ((Page.db.query(squish`
select count(*) from pages p
join questlines ql on p.id = ql.page_id
join quests qs on ql.id = qs.questline_id
where qs.completed = true
`).values()?.[0]?.[0] as number | bigint | undefined) ?? 0) > 0;
---
<div
hx-get={`/page/reset_button?page=${pageId}`}
hx-trigger="questComplete from:body"
>
<button
disabled={!canReset}
hx-post={`/event/page/reset?page=${pageId}`}
hx-target="closest div"
hx-swap="outerHTML"
>
Reset
</button>
</div>

View file

@ -0,0 +1,63 @@
---
export const partial = true;
export const prerender = false;
import { getSeasonStart } from '@postlight/seasons';
import { DateTime, Duration } from 'luxon';
import { Page } from '../../lib/Page';
const pageId = Astro.props.page ?? Astro.url.searchParams.get('page');
const schedule = Page.db.query("select reset_schedule from pages where id = ?").values(pageId)?.[0]?.[0];
const now = DateTime.now();
let stopstamp: number = 0
if (schedule === "daily") {
stopstamp = DateTime.local(now.year, now.month, now.day + 1, 1).toMillis();
} else if (schedule === "weekly") {
const day = now.weekday;
stopstamp = DateTime.local(now.year, now.month, now.day + (8 - day) % 7, 1).toMillis();
} else if (schedule === "fortnightly") {
const weeknum = now.weekNumber;
const day = now.weekday;
const toMonday = (8 - day) % 7;
const toFortnight = toMonday + (weeknum % 2) * 7;
stopstamp = DateTime.local(now.year, now.month, now.day + toFortnight, 1).toMillis();
} else if (schedule === "monthly") {
stopstamp = DateTime.local(now.year, now.month + 1, 1, 1).toMillis();
} else if (schedule === "seasonally") {
stopstamp = DateTime.fromJSDate(
getSeasonStart(now.month, now.year)
).toMillis();
}
let remaining = 'unknown'
if (stopstamp > 0) {
let precision = 0;
let ms = stopstamp - Date.now();
if (ms > 604_800_000) precision = 86_400_000;
else if (ms > 86_400_000) precision = 3_600_000;
else precision = 1000;
ms = Math.floor(ms / precision) * precision;
remaining = Duration.fromMillis(ms, { conversionAccuracy: 'longeterm' })
.rescale().toHuman({ unitDisplay: 'short' });
}
---
<span id="resetstamp">{remaining}</span>
<script define:vars={{ stopstamp }} is:inline type="module">
const el = document.getElementById('resetstamp');
if (el !== null && stopstamp > 0 && luxon) {
setInterval(() => {
let precision = 0;
let ms = stopstamp - Date.now();
if (ms > 604_800_000) precision = 86_400_000;
else if (ms > 86_400_000) precision = 3_600_000;
else precision = 1000;
ms = Math.floor(ms / precision) * precision;
el.innerText= luxon.Duration.fromMillis(ms, { conversionAccuracy: 'longeterm' })
.rescale().toHuman({ unitDisplay: 'short' });
}, 500);
}
</script>

View file

@ -0,0 +1,70 @@
---
export const partial = true;
export const prerender = false;
import Currency from '../../components/Currency.astro';
import QuestlineClaimRow from './claim_row.astro';
import QuestRow from '../QuestRow.astro';
import { Quest } from '../../lib/Quest';
import { Questline } from '../../lib/Questline';
const id = Astro.props.id ?? Astro.params.id;
const questline = Questline.load(id);
const questIds = Quest.db
.query('select id from quests where questline_id = ? order by sort_order')
.values(id)
.map(([id]) => id as number);
---
<fieldset class="questline"
hx-trigger="claimedAll from:body, reset from:body"
hx-get={`/questline/${id}`}
hx-target="this"
hx-swap="outerHTML"
>
<legend>
<span class="viewMode">{questline.name}</span>
<input class="name editMode" name="name" value={questline.name}
hx-post=`/event/questline/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous"
hx-swap="textContent"
/>
</legend>
<QuestlineClaimRow id={id} />
{questIds.map((questId: number) => (<QuestRow id={questId} />))}
<form class="editMode addQuest" hx-on::after-request="if(event.detail.successful) this.reset()">
<input name="name" placeholder="Quest" autofocus />
<Currency chorecoin>
<input name="reward" class="coins-reward" placeholder="0" type="number" />
</Currency>
<button
hx-put=`/event/quest/create?questline=${id}`
hx-target="closest fieldset"
hx-swap="outerHTML"
>Create</button>
</form>
</fieldset>
<style>
form.editMode {
gap: 0.5em;
input[name="name"] {
flex-grow: 1;
}
}
.questline {
display: flex;
flex-direction: column;
gap: 0.5em;
}
legend {
display: flex;
align-items: center;
gap: 1rem;
}
</style>

View file

@ -0,0 +1,64 @@
---
export const prerender = false;
export const partial = true;
import Currency from '../../components/Currency.astro';
import { Model } from '../../lib/Model';
import { Questline } from '../../lib/Questline';
const id = Astro.props?.id ?? Astro.url.searchParams.get('id');
const questline = Questline.load(id);
const allDone = Model.db.query(
'select count(*) from quests where questline_id=? and completed=false'
).values(id)[0][0] === 0;
---
<div class={ allDone ? 'allDone complete' : 'allDone incomplete' }
hx-get={`/questline/claim_row?id=${id}`}
hx-trigger={`questComplete-ql${id} from:body`}
hx-swap="outerHTML"
hx-target="this"
>
<span>
{ allDone ? 'All quests complete!' : 'Complete all quests to claim!' }
</span>
<Currency class="coins-reward viewMode" chorecoin>{questline.coinsReward}</Currency>
<Currency class="coins-reward editMode" chorecoin>
<input class="coins-reward" name="coinsReward" value={questline.coinsReward}
type="number"
hx-post=`/event/questline/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous span"
hx-swap="textContent"
/>
</Currency>
<button
disabled={!allDone || questline.claimed}
hx-post={`/event/questline/claim?id=${id}`}
hx-disabled-elt="this"
class="viewMode"
>
Claim{questline.claimed ? "ed!" : ""}
</button>
<button disabled class="editMode">
Claim{questline.claimed ? "ed!" : ""}
</button>
</div>
<style>
.allDone {
display: flex;
flex-direction: row;
width: 100%;
span {
flex-grow: 1
}
font-size: 80%;
gap: 1em;
&.incomplete {
color: #aaa;
}
}
</style>

127
src/pages/reward/list.astro Normal file
View file

@ -0,0 +1,127 @@
---
export const partial = true;
export const prerender = false;
import Currency from '../../components/Currency.astro';
import { Model } from '../../lib/Model';
import { RewardState } from '../../lib/Reward';
import { squish } from '../../lib/tags';
const rewards = Model.db.query(squish`
select id, name, link, gems_cost, chance
from rewards
where state > ${String(RewardState.deleted)}
order by sort_order
`).values() as Array<[number, string, string, number, number]>;
const bankedGems = Number.parseInt(Model.db.query(
'select ifnull(sum(gems_claimed), 0) - ifnull(sum(gems_spent), 0) from events'
).values()?.[0]?.[0], 10);
---
<div id="rewards" hx-get="/reward/list" hx-trigger="rewardEdit from:body" hx-swap="outerHTML">
<div class="header name">Reward</div>
<div class="header gems">Purchase</div>
<div class="header chance">Chance</div>
{ rewards.map(([id, name, link, gemsCost, chance]) => (
<>
<div class="name">
{ link?.length
? <a class="viewMode" href={link}>{name}</a>
: <span class="viewMode">{name}</span>
}
<div class="editMode buttons" hx-target="#rewards">
<button hx-post={`/event/reward/reorder?up&id=${id}`}>^</button>
<button hx-post={`/event/reward/delete?id=${id}`}>x</button>
<button hx-post={`/event/reward/reorder?down&id=${id}`}>v</button>
</div>
<input class="editMode" name="name" value={name}
placeholder="name"
hx-post=`/event/reward/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous .viewMode"
hx-swap="outerHTML"
/>
<input class="editMode" name="link" value={link}
placeholder="link"
hx-post=`/event/reward/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous .viewMode"
hx-swap="outerHTML"
/>
</div>
<div class="gems">
<button class="viewMode" disabled={gemsCost > bankedGems}>
<Currency gem>{gemsCost}</Currency>
</button>
<span class="editMode dollars">
<input name="dollars" placeholder="0.00" type="number" step="0.01"
value={gemsCost / 200}
hx-post=`/event/reward/edit?id=${id}`
hx-trigger="change changed"
hx-target="previous .viewMode"
hx-swap="textContent"
/>
</span>
</div>
<div class="chance">
<span class="viewMode">
{(Number.parseFloat(chance) * 100).toPrecision(2)}%
</span>
</div>
</>
))}
</div>
<style>
.header {
font-weight: bold;
}
.buttons.editMode {
flex-direction: column;
gap: 0;
font-size: x-small;
opacity: 100%;
button {
margin: 0 0 0 -1em;
}
}
#rewards {
display: grid;
grid-template-columns: 1fr max-content max-content;
margin-top: 1em;
gap: 1em;
> div {
display: flex;
gap: 1em;
}
}
.gems {
display: flex;
justify-content: flex-end;
}
input {
width: 15ch;
&[name="name"] {
flex-grow: 1;
}
&[name="dollars"] {
width: 7ch;
}
}
.dollars {
position: relative;
font-family: monospace;
}
.dollars::before {
content: "$";
position: absolute;
left: 0.25em;
}
</style>

13
tsconfig.json Normal file
View file

@ -0,0 +1,13 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}