diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6ac830..5ee256f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,12 +11,33 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 with: bun-version: latest + # The test suite runs on Bun, but users run the published CLI on Node. + - uses: actions/setup-node@v7 + with: + node-version: "24" - run: bun install --frozen-lockfile - run: bun run check - run: bun prettier --check . - run: bun test tests/unit/ tests/e2e/ - run: bun run build + - run: bun run docs:build + + # Installs the real tarball and loads a config in a CommonJS project — + # the default `npm init` layout, where Node's type stripping treats a + # `.ts` config as CommonJS and its `import` line fails to parse. + - name: Smoke-test the package on Node + run: | + set -euo pipefail + npm pack --pack-destination "$RUNNER_TEMP" + mkdir -p "$RUNNER_TEMP/smoke/src" + cd "$RUNNER_TEMP/smoke" + npm init -y > /dev/null + npm install "$RUNNER_TEMP"/srcpack-*.tgz > /dev/null + echo 'export const x = 1;' > src/index.ts + printf 'import { defineConfig } from "srcpack";\nexport default defineConfig({ bundles: { app: "src/**/*" } });\n' > srcpack.config.mts + ./node_modules/.bin/srcpack --dry-run | tee out.txt + grep -q 'src/index.ts' out.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..5e4bec5 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,45 @@ +# Docs ship with the release, not with every push, so the site always +# describes the version on npm. Use workflow_dispatch for typo fixes. +name: Docs + +on: + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + deploy: + # A prerelease is not what `npm install srcpack` gives you, so it must not + # rewrite the site. Manual dispatch carries no release payload and so passes. + if: github.event_name == 'workflow_dispatch' || !github.event.release.prerelease + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deploy.outputs.page_url }} + steps: + - uses: actions/checkout@v7 + with: + # VitePress reads "Last updated" and sitemap from per-file git + # history. The default shallow clone dates every page to the release + # commit, so all timestamps collapse to one. + fetch-depth: 0 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - run: bun install --frozen-lockfile + - run: bun run docs:build + - uses: actions/configure-pages@v6 + - uses: actions/upload-pages-artifact@v5 + with: + path: .vitepress/dist + - id: deploy + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ec8fe58..70ea190 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,12 +12,13 @@ jobs: id-token: write contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - - uses: actions/setup-node@v6 + - uses: actions/setup-node@v7 with: + # Stay on LTS for the publish job; v26 becomes LTS 2026-10-28. node-version: "24" registry-url: "https://registry.npmjs.org" - run: bun install --frozen-lockfile diff --git a/.vitepress/config.ts b/.vitepress/config.ts index a0185b3..2fc88a4 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -15,7 +15,9 @@ export default defineConfig({ description: "Context bundler for LLM work", head: [ - ["link", { rel: "icon", href: "/srcpack/favicon.ico" }], + // Point at files that exist in public/ — there is no favicon.ico + ["link", { rel: "icon", type: "image/svg+xml", href: "/srcpack/logo.svg" }], + ["link", { rel: "icon", type: "image/png", href: "/srcpack/logo.png" }], ["meta", { name: "theme-color", content: "#5f67ee" }], ["meta", { property: "og:type", content: "website" }], ["meta", { property: "og:site_name", content: "Srcpack" }], @@ -79,6 +81,7 @@ export default defineConfig({ nav: [ { text: "Home", link: "/" }, { text: "Guide", link: "/getting-started" }, + { text: "Decisions", link: "/adr/" }, ], sidebar: [ @@ -92,6 +95,16 @@ export default defineConfig({ { text: "Google Drive Upload", link: "/upload" }, ], }, + { + text: "Architecture Decisions", + items: [ + { text: "Overview", link: "/adr/" }, + { + text: "001 — git: source tokens", + link: "/adr/001-git-source-tokens", + }, + ], + }, ], outline: { diff --git a/README.md b/README.md index a6a6531..4f37ecd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Zero-config CLI for bundling code into LLM-optimized context files. -**Requirements:** Node.js 20+ or Bun +**Requirements:** Node.js 22.18+ or Bun ## Quick Start @@ -17,7 +17,7 @@ LLM context fails when codebases are large, noisy, or poorly organized. Srcpack ## Configuration -Create `srcpack.config.ts` in your project root: +Create `srcpack.config.ts` in your project root (use `srcpack.config.mts` if your `package.json` lacks `"type": "module"` — `srcpack init` picks the right one): ```typescript import { defineConfig } from "srcpack"; @@ -55,7 +55,7 @@ Or add to `package.json`: | `bundles` | — | Named bundles with glob patterns | | `upload` | — | Upload destination(s) | -\*`emptyOutDir` defaults to `true` when `outDir` is inside project root. When `outDir` is outside root, a warning is emitted unless explicitly set. +\*`emptyOutDir` defaults to `true` when `outDir` is inside project root. When `outDir` is outside root, a warning is emitted unless explicitly set. Emptying happens only on a full run, so `npx srcpack web` leaves other bundles in place. ### Bundle Config @@ -69,6 +69,9 @@ Or add to `package.json`: // Force-include gitignored files (+ prefix) ["docs/**/*", "+docs/**/*.local.md"] +// Changed files instead of a glob (git: prefix) +["git:staged", "!bun.lock"] + // Full options { include: "src/**/*", @@ -80,15 +83,15 @@ Or add to `package.json`: Patterns follow glob syntax. Prefix with `!` to exclude, `+` to force-include (bypasses `.gitignore`). Binary files are excluded. +A pattern can also name a set of changed files: `git:staged`, `git:unstaged`, `git:untracked`, `git:dirty`, or `git:` (e.g. `git:main`, `git:HEAD~3`). Deleted files are skipped, and `git:` compares against the merge base so a stale branch still reports only your own changes. See [Git sources](https://kriasoft.com/srcpack/configuration#git-sources-git-prefix). + ### Google Drive Upload To upload bundles to Google Drive, add OAuth credentials to your config: ```typescript export default defineConfig({ - bundles: { - /* ... */ - }, + bundles: {/* ... */}, upload: { provider: "gdrive", folderId: "1ABC...", // Google Drive folder ID (from URL) @@ -134,6 +137,9 @@ export function utils() { ```bash npx srcpack # Bundle all, upload if configured npx srcpack web api # Bundle specific bundles only +npx srcpack --staged # Bundle staged changes (no config needed) +npx srcpack --dirty # Bundle staged + unstaged + untracked +npx srcpack --since main # Bundle changes since main npx srcpack --dry-run # Preview without writing files npx srcpack --emptyOutDir # Empty output directory before bundling npx srcpack --no-emptyOutDir # Keep existing files in output directory diff --git a/bun.lock b/bun.lock index f553d08..7140073 100644 --- a/bun.lock +++ b/bun.lock @@ -5,109 +5,54 @@ "": { "name": "srcpack", "dependencies": { - "@clack/prompts": "^0.11.0", - "@googleapis/drive": "^20.0.0", - "cosmiconfig": "^9.0.0", + "@clack/prompts": "^1.7.0", + "@googleapis/drive": "^21.0.0", + "cosmiconfig": "^10.0.0", "fast-glob": "^3.3.3", - "google-auth-library": "^10.5.0", - "ignore": "^7.0.5", - "oauth-callback": "^1.2.5", - "ora": "^9.1.0", - "picomatch": "^4.0.2", - "zod": "^4.3.5", + "google-auth-library": "10.5.0", + "ignore": "^7.0.6", + "oauth-callback": "^2.2.0", + "ora": "^9.4.1", + "picomatch": "^4.0.5", + "zod": "^4.4.3", }, "devDependencies": { - "@types/bun": "^1.3.6", - "@types/picomatch": "^4.0.2", - "gh-pages": "^6.3.0", - "prettier": "^3.8.1", - "typescript": "^5.9.3", - "vitepress": "^2.0.0-alpha.15", - "vitepress-plugin-llms": "^1.10.0", + "@types/bun": "^1.3.14", + "@types/picomatch": "^4.0.3", + "prettier": "^3.9.6", + "typescript": "^6.0.3", + "vitepress": "^2.0.0-alpha.19", + "vitepress-plugin-llms": "^1.13.5", }, }, }, "packages": { - "@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="], + "@11ty/gray-matter": ["@11ty/gray-matter@2.1.0", "", { "dependencies": { "js-yaml": "^4.2.0", "section-matter": "^1.0.0" } }, "sha512-fNdBOb3MgDz/1UCIoeY4wDuGbp+/3s5y6UrsyfMabECbh/CVycj7Er33JXqSxRwxrRKXcGE1Jipuq/1mODInsQ=="], - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], - "@babel/parser": ["@babel/parser@7.28.6", "", { "dependencies": { "@babel/types": "^7.28.6" }, "bin": "./bin/babel-parser.js" }, "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ=="], + "@babel/parser": ["@babel/parser@7.29.8", "", { "dependencies": { "@babel/types": "^7.29.8" }, "bin": "./bin/babel-parser.js" }, "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA=="], - "@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="], + "@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="], - "@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="], + "@clack/core": ["@clack/core@1.4.3", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ=="], - "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + "@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="], - "@docsearch/css": ["@docsearch/css@4.5.3", "", {}, "sha512-kUpHaxn0AgI3LQfyzTYkNUuaFY4uEz/Ym9/N/FvyDE+PzSgZsCyDH9jE49B6N6f1eLCm9Yp64J9wENd6vypdxA=="], + "@docsearch/css": ["@docsearch/css@4.7.0", "", {}, "sha512-Sk5xkdRFeE7PeWjG9l4AfTwdvMfr9wHiwNNCpHXT4v4SNyNMKdHGvEILc31BgaVFGDDNbv5u/a73tofRiwbEZw=="], - "@docsearch/js": ["@docsearch/js@4.5.3", "", {}, "sha512-rcBiUMCXbZLqrLIT6F6FDcrG/tyvM2WM0zum6NPbIiQNDQxbSgmNc+/bToS0rxBsXaxiU64esiWoS02WqrWLsg=="], + "@docsearch/js": ["@docsearch/js@4.7.0", "", {}, "sha512-x5lCqu1tetgsJFkjQ6VSocbHldsRkGEgwg5N98Vx21sq/V5wcmj4u226PY9k+TEpIgQ772zlYbPLTPicWyGnpA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + "@docsearch/sidepanel-js": ["@docsearch/sidepanel-js@4.7.0", "", {}, "sha512-A8r34jCU8kcIk2viECEn2msA28ojUF1BLi/3v5OWWc5G2N3jOuuumBXoeYjfr8dA0UxgFSy5R2bt12dnFJQSyA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + "@googleapis/drive": ["@googleapis/drive@21.0.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-vebQpAqn+FZcmDWh1TEQTcYdkKftcSaHc7kO2ZxrINBb+ZMcFu1UybD3+maeqdLs60HrRDYwyzJ6TgZ7/Vn2Rg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], - - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], - - "@googleapis/drive": ["@googleapis/drive@20.0.0", "", { "dependencies": { "googleapis-common": "^8.0.0" } }, "sha512-qLi5ypZn0zYY2FcGjdlHQsv1DAFNRwCWFiE5kq23J0yTdUSZynh/mDph9NBaiQ9ybajrmttySR/rSaNfm8S/bA=="], - - "@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.67", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-RGJRwlxyup54L1UDAjCshy3ckX5zcvYIU74YLSnUgHGvqh6B4mvksbGNHAIEp7dZQ6cM13RZVT5KC07CmnFNew=="], + "@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.93", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-/XhANjfGYOuqvSR3TmUnkQkINvQ4GVjVuukvymRbxtVFBvIq/yiXJqCDycKcQPT401OYT9H2vIY6ihAlz1QIAw=="], "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], - "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], - - "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], @@ -118,83 +63,63 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.53", "", {}, "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ=="], + "@oxc-project/types": ["@oxc-project/types@0.144.0", "", {}, "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.56.0", "", { "os": "android", "cpu": "arm" }, "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.56.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.56.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.56.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.56.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.56.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.4", "", { "os": "android", "cpu": "arm64" }, "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg=="], + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ=="], - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA=="], + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.56.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw=="], + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A=="], - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.56.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg=="], + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.56.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ=="], + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw=="], + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA=="], + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ=="], - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.56.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA=="], + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.56.0", "", { "os": "none", "cpu": "arm64" }, "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ=="], + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.4", "", { "os": "none", "cpu": "arm64" }, "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.56.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing=="], + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.56.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg=="], + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g=="], + "@shikijs/core": ["@shikijs/core@4.4.3", "", { "dependencies": { "@shikijs/primitive": "4.4.3", "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" } }, "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg=="], - "@shikijs/core": ["@shikijs/core@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA=="], + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.4.3", "", { "dependencies": { "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ=="], - "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ=="], + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.4.3", "", { "dependencies": { "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w=="], - "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ=="], + "@shikijs/langs": ["@shikijs/langs@4.4.3", "", { "dependencies": { "@shikijs/types": "4.4.3" } }, "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A=="], - "@shikijs/langs": ["@shikijs/langs@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0" } }, "sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA=="], + "@shikijs/primitive": ["@shikijs/primitive@4.4.3", "", { "dependencies": { "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" } }, "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ=="], - "@shikijs/themes": ["@shikijs/themes@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0" } }, "sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw=="], + "@shikijs/themes": ["@shikijs/themes@4.4.3", "", { "dependencies": { "@shikijs/types": "4.4.3" } }, "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw=="], - "@shikijs/transformers": ["@shikijs/transformers@3.21.0", "", { "dependencies": { "@shikijs/core": "3.21.0", "@shikijs/types": "3.21.0" } }, "sha512-CZwvCWWIiRRiFk9/JKzdEooakAP8mQDtBOQ1TKiCaS2E1bYtyBCOkUzS8akO34/7ufICQ29oeSfkb3tT5KtrhA=="], + "@shikijs/transformers": ["@shikijs/transformers@4.4.3", "", { "dependencies": { "@shikijs/core": "4.4.3", "@shikijs/types": "4.4.3" } }, "sha512-oJSARV6NaWd+rnNJbtnpAdj3Zg0ZVyzsnMgb3vi3HA+35y8lBWUCpOnWsmyiXZIikY+x1BDqrQUgmxfzWh7Jvw=="], - "@shikijs/types": ["@shikijs/types@3.21.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA=="], + "@shikijs/types": ["@shikijs/types@4.4.3", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" } }, "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g=="], "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], - - "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], - "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + "@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="], "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="], @@ -206,65 +131,61 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], + "@types/node": ["@types/node@26.2.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="], - "@types/picomatch": ["@types/picomatch@4.0.2", "", {}, "sha512-qHHxQ+P9PysNEGbALT8f8YOSHW0KJu6l2xU8DYY0fu/EmGxXdVnuTLvFUvBgPJMSqXq29SYHveejeAha+4AYgA=="], + "@types/picomatch": ["@types/picomatch@4.0.3", "", {}, "sha512-iG0T6+nYJ9FAPmx9SsUlnwcq1ZVRuCXcVEvWnntoPlrOpwtSTKNDC9uVAxTsC3PUvJ+99n4RpAcNgBbHX3JSnQ=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="], - "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.3", "", {}, "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg=="], - "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.3", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.53" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "vue": "^3.2.25" } }, "sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w=="], + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.8", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew=="], - "@vue/compiler-core": ["@vue/compiler-core@3.5.27", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/shared": "3.5.27", "entities": "^7.0.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ=="], + "@vue/compiler-core": ["@vue/compiler-core@3.5.41", "", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/shared": "3.5.41", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg=="], - "@vue/compiler-dom": ["@vue/compiler-dom@3.5.27", "", { "dependencies": { "@vue/compiler-core": "3.5.27", "@vue/shared": "3.5.27" } }, "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w=="], + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.41", "", { "dependencies": { "@vue/compiler-core": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw=="], - "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.27", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/compiler-core": "3.5.27", "@vue/compiler-dom": "3.5.27", "@vue/compiler-ssr": "3.5.27", "@vue/shared": "3.5.27", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ=="], + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.41", "", { "dependencies": { "@babel/parser": "^7.29.8", "@vue/compiler-core": "3.5.41", "@vue/compiler-dom": "3.5.41", "@vue/compiler-ssr": "3.5.41", "@vue/shared": "3.5.41", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.19", "source-map-js": "^1.2.1" } }, "sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ=="], - "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.27", "", { "dependencies": { "@vue/compiler-dom": "3.5.27", "@vue/shared": "3.5.27" } }, "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw=="], + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.41", "", { "dependencies": { "@vue/compiler-dom": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A=="], - "@vue/devtools-api": ["@vue/devtools-api@8.0.5", "", { "dependencies": { "@vue/devtools-kit": "^8.0.5" } }, "sha512-DgVcW8H/Nral7LgZEecYFFYXnAvGuN9C3L3DtWekAncFBedBczpNW8iHKExfaM559Zm8wQWrwtYZ9lXthEHtDw=="], + "@vue/devtools-api": ["@vue/devtools-api@8.2.1", "", { "dependencies": { "@vue/devtools-kit": "^8.2.1" } }, "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A=="], - "@vue/devtools-kit": ["@vue/devtools-kit@8.0.5", "", { "dependencies": { "@vue/devtools-shared": "^8.0.5", "birpc": "^2.6.1", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^2.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg=="], + "@vue/devtools-kit": ["@vue/devtools-kit@8.2.1", "", { "dependencies": { "@vue/devtools-shared": "^8.2.1", "birpc": "^2.6.1", "hookable": "^5.5.3", "perfect-debounce": "^2.0.0" } }, "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ=="], - "@vue/devtools-shared": ["@vue/devtools-shared@8.0.5", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg=="], + "@vue/devtools-shared": ["@vue/devtools-shared@8.2.1", "", {}, "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g=="], - "@vue/reactivity": ["@vue/reactivity@3.5.27", "", { "dependencies": { "@vue/shared": "3.5.27" } }, "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ=="], + "@vue/reactivity": ["@vue/reactivity@3.5.41", "", { "dependencies": { "@vue/shared": "3.5.41" } }, "sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA=="], - "@vue/runtime-core": ["@vue/runtime-core@3.5.27", "", { "dependencies": { "@vue/reactivity": "3.5.27", "@vue/shared": "3.5.27" } }, "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A=="], + "@vue/runtime-core": ["@vue/runtime-core@3.5.41", "", { "dependencies": { "@vue/reactivity": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg=="], - "@vue/runtime-dom": ["@vue/runtime-dom@3.5.27", "", { "dependencies": { "@vue/reactivity": "3.5.27", "@vue/runtime-core": "3.5.27", "@vue/shared": "3.5.27", "csstype": "^3.2.3" } }, "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg=="], + "@vue/runtime-dom": ["@vue/runtime-dom@3.5.41", "", { "dependencies": { "@vue/reactivity": "3.5.41", "@vue/runtime-core": "3.5.41", "@vue/shared": "3.5.41", "csstype": "^3.2.3" } }, "sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw=="], - "@vue/server-renderer": ["@vue/server-renderer@3.5.27", "", { "dependencies": { "@vue/compiler-ssr": "3.5.27", "@vue/shared": "3.5.27" }, "peerDependencies": { "vue": "3.5.27" } }, "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA=="], + "@vue/server-renderer": ["@vue/server-renderer@3.5.41", "", { "dependencies": { "@vue/compiler-ssr": "3.5.41", "@vue/runtime-dom": "3.5.41", "@vue/shared": "3.5.41" } }, "sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ=="], - "@vue/shared": ["@vue/shared@3.5.27", "", {}, "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ=="], + "@vue/shared": ["@vue/shared@3.5.41", "", {}, "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA=="], - "@vueuse/core": ["@vueuse/core@14.1.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "14.1.0", "@vueuse/shared": "14.1.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-rgBinKs07hAYyPF834mDTigH7BtPqvZ3Pryuzt1SD/lg5wEcWqvwzXXYGEDb2/cP0Sj5zSvHl3WkmMELr5kfWw=="], + "@vueuse/core": ["@vueuse/core@14.4.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "14.4.0", "@vueuse/shared": "14.4.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ=="], - "@vueuse/integrations": ["@vueuse/integrations@14.1.0", "", { "dependencies": { "@vueuse/core": "14.1.0", "@vueuse/shared": "14.1.0" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7 || ^8", "vue": "^3.5.0" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "fuse.js", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-eNQPdisnO9SvdydTIXnTE7c29yOsJBD/xkwEyQLdhDC/LKbqrFpXHb3uS//7NcIrQO3fWVuvMGp8dbK6mNEMCA=="], + "@vueuse/integrations": ["@vueuse/integrations@14.4.0", "", { "dependencies": { "@vueuse/core": "14.4.0", "@vueuse/shared": "14.4.0" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7 || ^8", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7 || ^8", "vue": "^3.5.0" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "fuse.js", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-oJz9qTgczvA7L1nXQFRU7h8tQbOCoiceqvMMhT9XYMyOGTqLJ2rEa09PON+nD2t48sZUfeOmg4eaWJXV4sZb/w=="], - "@vueuse/metadata": ["@vueuse/metadata@14.1.0", "", {}, "sha512-7hK4g015rWn2PhKcZ99NyT+ZD9sbwm7SGvp7k+k+rKGWnLjS/oQozoIZzWfCewSUeBmnJkIb+CNr7Zc/EyRnnA=="], + "@vueuse/metadata": ["@vueuse/metadata@14.4.0", "", {}, "sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g=="], - "@vueuse/shared": ["@vueuse/shared@14.1.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-EcKxtYvn6gx1F8z9J5/rsg3+lTQnvOruQd8fUecW99DCK04BkWD7z5KQ/wTAx+DazyoEE9dJt/zV8OIEQbM6kw=="], + "@vueuse/shared": ["@vueuse/shared@14.4.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], - "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "ansi-regex": ["ansi-regex@6.3.0", "", {}, "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], - - "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], - "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], @@ -272,22 +193,18 @@ "birpc": ["birpc@2.9.0", "", {}, "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw=="], - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], - "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], - - "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -310,13 +227,7 @@ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], - - "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], - - "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="], - - "cosmiconfig": ["cosmiconfig@9.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="], + "cosmiconfig": ["cosmiconfig@10.0.0", "", { "dependencies": { "env-paths": "^2.2.1", "js-yaml": "^4.1.0" } }, "sha512-RYs2EfrIoS16yh6j/MLgF753u5rROFFw3XGjcJXM4UQJm1iGXX7gKNyk4O/bCkyfi9Qfo+fVdd3FrnviZv830g=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -324,21 +235,15 @@ "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], - "default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="], - - "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], - - "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], - "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], @@ -346,29 +251,21 @@ "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - "email-addresses": ["email-addresses@5.0.0", "", {}, "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw=="], - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], - - "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - "escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], @@ -378,6 +275,12 @@ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="], + + "fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="], + + "fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], @@ -386,17 +289,9 @@ "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], - "filename-reserved-regex": ["filename-reserved-regex@2.0.0", "", {}, "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ=="], - - "filenamify": ["filenamify@4.3.0", "", { "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", "trim-repeated": "^1.0.0" } }, "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg=="], - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - "find-cache-dir": ["find-cache-dir@3.3.2", "", { "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" } }, "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig=="], - - "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], - - "focus-trap": ["focus-trap@7.8.0", "", { "dependencies": { "tabbable": "^6.4.0" } }, "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA=="], + "focus-trap": ["focus-trap@8.2.2", "", { "dependencies": { "tabbable": "^6.5.0" } }, "sha512-qV0g8hRYBqgACcFOH3f9wXc4zPKhr/0z9RI2a6ZijZ72EeBi4g8oBy8zAWuUR1TsMpOzwpUMFvjdasrC41Joug=="], "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], @@ -404,49 +299,39 @@ "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], - "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], + "gaxios": ["gaxios@7.3.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ=="], "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], - "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], + "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - "gh-pages": ["gh-pages@6.3.0", "", { "dependencies": { "async": "^3.2.4", "commander": "^13.0.0", "email-addresses": "^5.0.0", "filenamify": "^4.3.0", "find-cache-dir": "^3.3.1", "fs-extra": "^11.1.1", "globby": "^11.1.0" }, "bin": { "gh-pages": "bin/gh-pages.js", "gh-pages-clean": "bin/gh-pages-clean.js" } }, "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA=="], - "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], - "google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], - "googleapis-common": ["googleapis-common@8.0.1", "", { "dependencies": { "extend": "^3.0.2", "gaxios": "^7.0.0-rc.4", "google-auth-library": "^10.1.0", "qs": "^6.7.0", "url-template": "^2.0.8" } }, "sha512-eCzNACUXPb1PW5l0ULTzMHaL/ltPRADoPgjBlT8jWsTbxkCp6siv+qKJ/1ldaybCthGwsYFYallF7u9AkU4L+A=="], + "googleapis-common": ["googleapis-common@8.0.3", "", { "dependencies": { "extend": "^3.0.2", "gaxios": "7.1.3", "google-auth-library": "10.5.0", "google-logging-utils": "1.1.3", "qs": "^6.7.0", "url-template": "^2.0.8" } }, "sha512-7g1yzQKx0mmNTjiK0H9dJ8eqKqDBveES9vLHeg5neb3BMQy/d1oQefIMhIpOVT8a+f+LOcixMEdRbFIW/cQUJw=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - - "gray-matter": ["gray-matter@4.0.3", "", { "dependencies": { "js-yaml": "^3.13.1", "kind-of": "^6.0.2", "section-matter": "^1.0.0", "strip-bom-string": "^1.0.0" } }, "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q=="], - "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], "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=="], @@ -458,13 +343,7 @@ "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - - "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], @@ -474,10 +353,6 @@ "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="], - - "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-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], @@ -486,35 +361,45 @@ "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], - "is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="], - - "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="], "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], - - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], - "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], "kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="], - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="], - "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], - "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + "linkify-it": ["linkify-it@5.0.2", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q=="], "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], @@ -524,17 +409,15 @@ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], - "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], - "mark.js": ["mark.js@8.11.1", "", {}, "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="], - "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="], + "markdown-it": ["markdown-it@14.3.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.5.0", "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw=="], "markdown-title": ["markdown-title@1.0.2", "", {}, "sha512-MqIQVVkz+uGEHi3TsHx/czcxxCbRIL7sv5K5DnYw/tI+apY54IbPefV/cmgxp6LoJSEx/TqcHdLs/298afG5QQ=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], - "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-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "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-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], "mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="], @@ -546,7 +429,7 @@ "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], - "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="], + "mdurl": ["mdurl@2.1.0", "", {}, "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], @@ -600,79 +483,57 @@ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], - "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="], - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], "minisearch": ["minisearch@7.2.0", "", {}, "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg=="], - "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], - "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=="], + "nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "oauth-callback": ["oauth-callback@1.2.5", "", { "dependencies": { "open": "^11.0.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": ">=1.17.0 <2", "typescript": ">=5 <6" }, "optionalPeers": ["@modelcontextprotocol/sdk", "typescript"] }, "sha512-xf9YpP8Ocml/+Vt+cGLWDQB+BV4BlELIjO+6QNg46l1J91j4faezBAzLxSxwzfaF4xzGpQmtuULUPO7aoigdkg=="], + "oauth-callback": ["oauth-callback@2.2.0", "", { "peerDependencies": { "@modelcontextprotocol/sdk": ">=1.17.0 <2", "typescript": ">=5 <6" }, "optionalPeers": ["@modelcontextprotocol/sdk", "typescript"] }, "sha512-ydyRl3cYH9x6BnJC2sjqu1uHUUYCmHnDweqLcT5cxSdDoIIBRunwUaJrFqdsTkiVZrLi1xwLHfRalBVAVZJ6pQ=="], "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="], - - "oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="], - - "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], + "oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="], - "ora": ["ora@9.1.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.2.2", "string-width": "^8.1.0" } }, "sha512-53uuLsXHOAJl5zLrUrzY9/kE+uIFEx7iaH4g2BIJQK4LZjY4LpCCYZVKDWIkL+F01wAaCg93duQ1whnK/AmY1A=="], + "oniguruma-to-es": ["oniguruma-to-es@4.3.6", "", { "dependencies": { "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA=="], - "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - - "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - - "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + "ora": ["ora@9.4.1", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.2", "string-width": "^8.1.0" } }, "sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw=="], "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="], - - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], - "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], + "postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="], - "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], + "prettier": ["prettier@3.9.6", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g=="], - "pretty-bytes": ["pretty-bytes@7.1.0", "", {}, "sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw=="], + "pretty-bytes": ["pretty-bytes@7.1.1", "", {}, "sha512-X+vn9z8nOFZQlxOLmfJ0iKDdMD7jYTsTW12OAlCpdoE3Igik6L37pugIZi+N3usuyp5McfgKPWi12q3zvHLeGQ=="], - "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], - "qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="], + "qs": ["qs@6.15.3", "", { "dependencies": { "es-define-property": "^1.0.1", "side-channel": "^1.1.1" } }, "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], @@ -692,19 +553,13 @@ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - "rollup": ["rollup@4.56.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.56.0", "@rollup/rollup-android-arm64": "4.56.0", "@rollup/rollup-darwin-arm64": "4.56.0", "@rollup/rollup-darwin-x64": "4.56.0", "@rollup/rollup-freebsd-arm64": "4.56.0", "@rollup/rollup-freebsd-x64": "4.56.0", "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", "@rollup/rollup-linux-arm-musleabihf": "4.56.0", "@rollup/rollup-linux-arm64-gnu": "4.56.0", "@rollup/rollup-linux-arm64-musl": "4.56.0", "@rollup/rollup-linux-loong64-gnu": "4.56.0", "@rollup/rollup-linux-loong64-musl": "4.56.0", "@rollup/rollup-linux-ppc64-gnu": "4.56.0", "@rollup/rollup-linux-ppc64-musl": "4.56.0", "@rollup/rollup-linux-riscv64-gnu": "4.56.0", "@rollup/rollup-linux-riscv64-musl": "4.56.0", "@rollup/rollup-linux-s390x-gnu": "4.56.0", "@rollup/rollup-linux-x64-gnu": "4.56.0", "@rollup/rollup-linux-x64-musl": "4.56.0", "@rollup/rollup-openbsd-x64": "4.56.0", "@rollup/rollup-openharmony-arm64": "4.56.0", "@rollup/rollup-win32-arm64-msvc": "4.56.0", "@rollup/rollup-win32-ia32-msvc": "4.56.0", "@rollup/rollup-win32-x64-gnu": "4.56.0", "@rollup/rollup-win32-x64-msvc": "4.56.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg=="], - - "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], + "rolldown": ["rolldown@1.2.4", "", { "dependencies": { "@oxc-project/types": "=0.144.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.2.4", "@rolldown/binding-darwin-arm64": "1.2.4", "@rolldown/binding-darwin-x64": "1.2.4", "@rolldown/binding-freebsd-x64": "1.2.4", "@rolldown/binding-linux-arm-gnueabihf": "1.2.4", "@rolldown/binding-linux-arm64-gnu": "1.2.4", "@rolldown/binding-linux-arm64-musl": "1.2.4", "@rolldown/binding-linux-ppc64-gnu": "1.2.4", "@rolldown/binding-linux-s390x-gnu": "1.2.4", "@rolldown/binding-linux-x64-gnu": "1.2.4", "@rolldown/binding-linux-x64-musl": "1.2.4", "@rolldown/binding-openharmony-arm64": "1.2.4", "@rolldown/binding-win32-arm64-msvc": "1.2.4", "@rolldown/binding-win32-x64-msvc": "1.2.4" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], @@ -712,17 +567,15 @@ "section-matter": ["section-matter@1.0.0", "", { "dependencies": { "extend-shallow": "^2.0.1", "kind-of": "^6.0.0" } }, "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA=="], - "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - "shiki": ["shiki@3.21.0", "", { "dependencies": { "@shikijs/core": "3.21.0", "@shikijs/engine-javascript": "3.21.0", "@shikijs/engine-oniguruma": "3.21.0", "@shikijs/langs": "3.21.0", "@shikijs/themes": "3.21.0", "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w=="], + "shiki": ["shiki@4.4.3", "", { "dependencies": { "@shikijs/core": "4.4.3", "@shikijs/engine-javascript": "4.4.3", "@shikijs/engine-oniguruma": "4.4.3", "@shikijs/langs": "4.4.3", "@shikijs/themes": "4.4.3", "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" } }, "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g=="], - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], - "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], @@ -732,53 +585,39 @@ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - "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=="], - "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="], - - "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], - - "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + "stdin-discarder": ["stdin-discarder@0.3.2", "", {}, "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A=="], - "string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="], + "string-width": ["string-width@8.2.2", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg=="], "string-width-cjs": ["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=="], "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.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "strip-bom-string": ["strip-bom-string@1.0.0", "", {}, "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g=="], - - "strip-outer": ["strip-outer@1.0.1", "", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg=="], - - "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="], - - "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="], + "tabbable": ["tabbable@6.5.0", "", {}, "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA=="], - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "tokenx": ["tokenx@1.2.1", "", {}, "sha512-lVhFIhR2qh3uUyUA8Ype+HGzcokUJbHmRSN1TJKOe4Y26HkawQuLiGkUCkR5LD9dx+Rtp+njrwzPL8AHHYQSYA=="], + "tokenx": ["tokenx@1.6.0", "", {}, "sha512-CKTjk345ajvBAUp5xUI9a5KKN0zU0lBueVHQbCskH1Hp6WkUKsPW2qGCYNs0pxNyfzxfo+IIjdt2W4sMbw/qBw=="], "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], - "trim-repeated": ["trim-repeated@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg=="], - "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], "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=="], @@ -790,25 +629,23 @@ "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": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], - "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - "url-template": ["url-template@2.0.8", "", {}, "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], - "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "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-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], + "vite": ["vite@8.2.1", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.5", "postcss": "^8.5.25", "rolldown": "~1.2.1", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.4.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw=="], - "vitepress": ["vitepress@2.0.0-alpha.15", "", { "dependencies": { "@docsearch/css": "^4.3.2", "@docsearch/js": "^4.3.2", "@iconify-json/simple-icons": "^1.2.59", "@shikijs/core": "^3.15.0", "@shikijs/transformers": "^3.15.0", "@shikijs/types": "^3.15.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^6.0.1", "@vue/devtools-api": "^8.0.5", "@vue/shared": "^3.5.24", "@vueuse/core": "^14.0.0", "@vueuse/integrations": "^14.0.0", "focus-trap": "^7.6.6", "mark.js": "8.11.1", "minisearch": "^7.2.0", "shiki": "^3.15.0", "vite": "^7.2.2", "vue": "^3.5.24" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "oxc-minify": "*", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "oxc-minify", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-jhjSYd10Z6RZiKOa7jy0xMVf5NB5oSc/lS3bD/QoUc6V8PrvQR5JhC9104NEt6+oTGY/ftieVWxY9v7YI+1IjA=="], + "vitepress": ["vitepress@2.0.0-alpha.19", "", { "dependencies": { "@docsearch/css": "^4.7.0", "@docsearch/js": "^4.7.0", "@docsearch/sidepanel-js": "^4.7.0", "@iconify-json/simple-icons": "^1.2.92", "@shikijs/core": "^4.4.1", "@shikijs/transformers": "^4.4.1", "@shikijs/types": "^4.4.1", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^6.0.8", "@vue/devtools-api": "^8.2.1", "@vue/shared": "^3.5.40", "@vueuse/core": "^14.4.0", "@vueuse/integrations": "^14.4.0", "focus-trap": "^8.2.2", "mark.js": "8.11.1", "minisearch": "^7.2.0", "shiki": "^4.4.1", "vite": "^8.2.0", "vue": "^3.5.40" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-WnBsb0Bwr43kXKyiis+lld/7ri3hnMbthS8N3hpFtjjwsdLO4IRmiAE08D7aud4q6oMDf9uwRowxzNqRFe/amw=="], - "vitepress-plugin-llms": ["vitepress-plugin-llms@1.10.0", "", { "dependencies": { "gray-matter": "^4.0.3", "markdown-it": "^14.1.0", "markdown-title": "^1.0.2", "mdast-util-from-markdown": "^2.0.2", "millify": "^6.1.0", "minimatch": "^10.1.1", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "pretty-bytes": "^7.1.0", "remark": "^15.0.1", "remark-frontmatter": "^5.0.0", "tokenx": "^1.2.1", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-dgD5KV8D9vXlQtAf/KUjSgr3QymH1fHT7XkQ/UuIqvIjnKdzZI+0gT3puGxUBuqgvlFjYWA6f8k80tXl6gwWkw=="], + "vitepress-plugin-llms": ["vitepress-plugin-llms@1.13.5", "", { "dependencies": { "@11ty/gray-matter": "^2.1.0", "markdown-it": "^14.1.0", "markdown-title": "^1.0.2", "mdast-util-from-markdown": "^2.0.3", "millify": "^6.1.0", "minimatch": "^10.2.6", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "pretty-bytes": "^7.1.1", "remark": "^15.0.1", "remark-frontmatter": "^5.0.0", "tokenx": "^1.6.0", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.1.0" } }, "sha512-CTiDkKRs0h64J5rdiICdHmXH4pM1gBu2S/MJ+OxSAm+vM72srBkHr86ZubzfMJbGJh4AMVKff4R3oCu8etI1ww=="], - "vue": ["vue@3.5.27", "", { "dependencies": { "@vue/compiler-dom": "3.5.27", "@vue/compiler-sfc": "3.5.27", "@vue/runtime-dom": "3.5.27", "@vue/server-renderer": "3.5.27", "@vue/shared": "3.5.27" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw=="], + "vue": ["vue@3.5.41", "", { "dependencies": { "@vue/compiler-dom": "3.5.41", "@vue/compiler-sfc": "3.5.41", "@vue/runtime-dom": "3.5.41", "@vue/server-renderer": "3.5.41", "@vue/shared": "3.5.41" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg=="], "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], @@ -818,17 +655,17 @@ "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], + + "yargs": ["yargs@17.7.3", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + "yoctocolors": ["yoctocolors@2.2.0", "", {}, "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg=="], - "zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], @@ -842,15 +679,11 @@ "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "googleapis-common/gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], - "gray-matter/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], - - "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -872,7 +705,7 @@ "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.1.4", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -882,6 +715,8 @@ "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], } } diff --git a/docs/adr/001-git-source-tokens.md b/docs/adr/001-git-source-tokens.md new file mode 100644 index 0000000..b42c8af --- /dev/null +++ b/docs/adr/001-git-source-tokens.md @@ -0,0 +1,88 @@ +# ADR 001: `git:` source tokens in the pattern language + +**Status:** Accepted — 2026-08-15 + +## Context + +Bundling "what I'm currently changing" is the most common ad-hoc need: hand an +LLM your staged diff, or everything on this branch, for review. Globs can't +express it — the file set comes from git, not from the filesystem layout. + +The obvious-looking API spreads a resolved list into the pattern array: + +```ts +review: [...$staged, "!bun.lock"]; +``` + +It reads well and it's wrong. A spread forces `$staged` to be concrete at +config **import** time, which means git runs when the module loads (even for +`srcpack docs`), the config stops being inspectable data, `package.json` config +becomes impossible, and import-time `cwd` may differ from the resolved `root`. +Worst of all, concrete paths land in an array that is later matched as globs, +so a staged file named `src/[id].tsx` silently matches nothing. + +## Decision + +A pattern may be a `git:` source instead of a glob, resolved lazily inside +`resolvePatterns()` alongside globs: + +```ts +review: ["git:staged", "!bun.lock"]; +``` + +Sources: `git:staged`, `git:unstaged`, `git:untracked`, `git:dirty`, and +`git:` for any revision or range. + +CLI flags `--staged`, `--dirty`, and `--since ` build a one-off bundle from +the same tokens, and work with no config file at all. + +Supporting decisions: + +- **Deleted and unmerged entries are filtered** (`--diff-filter=ACMR`), and + every candidate is stat-checked before bundling. Git lists paths; only some + of them are readable regular files (submodules, or a file deleted after git + listed it). +- **`git:` uses `git diff --merge-base`** for a single revision. `git:main` + on a branch that has fallen behind main would otherwise report other people's + commits. For an ancestor like `HEAD~3` the merge base is the revision itself, + so this is a no-op — one rule that's right in both cases. Ranges pass through + verbatim. +- **A source selects paths; content always comes from the worktree.** Reading + staged blobs would put content in the bundle that doesn't match the files on + disk — confusing when the LLM's answer cites a line. +- **`.gitignore` does not apply** to git sources. Anything git reports is either + tracked (possibly force-added past `.gitignore`, and deliberately so) or was + filtered by `--exclude-standard` already. +- **`!git:...` and `+git:...` are errors.** Exclusion has no clear meaning, and + force-include is already implied. Failing loudly beats a silent no-op. +- **Empty bundles are not written**, and a previous run's file is removed. + "Nothing staged" is routine, and a stale bundle that then gets uploaded to + Drive is worse than no file. +- **Symlinks are never followed** (`lstat`, not `stat`). Git happily tracks a + link pointing anywhere; following one would bundle a file from outside the + project under an innocuous in-repo name. +- **Ad-hoc CLI bundles are never uploaded.** The user configured upload for the + bundles they declared, and `upload.exclude` cannot name a bundle that only + exists for one run. +- **`outDir` and every configured `outfile` are excluded from every bundle.** + Ad-hoc runs don't empty `outDir`, so `git:untracked` reports the last run's + bundle and each rerun nests it one level deeper. + +## Alternatives + +- **Typed helpers** (`[staged(), "!bun.lock"]`) — real autocomplete, but the + array becomes `(string | Source)[]`, it can't work in `package.json`, and it + adds permanent public exports. +- **A `from` field** (`{ from: "staged", include: "src/**" }`) — conceptually + cleaner (a source isn't a glob), but adds a second axis plus an `exclude` + field, giving two ways to say the same thing. +- **An async resolver** (`include: async ({ git }) => …`) — maximum power, but + the config is no longer data and `git.*` becomes an API to maintain. + +## Consequences + +The pattern array gains a second kind of entry, so `git:` is now reserved as a +scheme (a branch named `staged` needs `git:refs/heads/staged`). In exchange +there is no new config shape, no new export, and the feature composes with `!` +exclusions and globs for free. Future non-glob sources can reuse the +`scheme:` convention. diff --git a/docs/adr/002-minimum-node-version.md b/docs/adr/002-minimum-node-version.md new file mode 100644 index 0000000..56f3f96 --- /dev/null +++ b/docs/adr/002-minimum-node-version.md @@ -0,0 +1,58 @@ +# ADR 002: Node 22.18 as the minimum runtime + +**Status:** Accepted — 2026-08-15 + +## Context + +`srcpack.config.ts` is the primary config format — the first entry in +`searchPlaces`, and what `srcpack init` writes. Loading TypeScript at runtime +is therefore not optional, and until now cosmiconfig carried its own +`typescript` dependency to do it. + +cosmiconfig 10 removes that dependency in favour of Node's built-in type +stripping, and requires `^22.18 || >=24`. Type stripping is enabled by default +from Node 22.18, so the loader works on any runtime cosmiconfig itself accepts — +but on Node 20 a `.ts` config now fails to load at all. + +The declared floor was `>=18.0.0`, which had already drifted from reality: +Node 18 reached end-of-life 2025-04-30 and Node 20 followed on 2026-04-30. + +## Decision + +`engines.node` becomes `^22.18.0 || >=24`, matching cosmiconfig's own range +rather than inventing a looser one. + +Pinning to the dependency's range is deliberate. A floor of `>=20` would install +cleanly and then fail at the first `srcpack.config.ts` — the failure would +surface as a confusing parse error rather than an unmet engine warning at +install time. + +## Alternatives + +- **Keep `>=18` and bundle a TypeScript parser** — restores Node 20 support at + the cost of a heavyweight dependency for a runtime everyone's package manager + already warns about. +- **Drop `.ts` config support below Node 22.18, keep the floor low** — two + behaviours for one documented feature, discovered only at run time. + +## Consequences + +Config files must use erasable syntax only. Type annotations, `satisfies`, and +`import type` are fine; `enum` and `namespace` are not — Node strips types, it +does not compile them. `defineConfig` objects use none of the latter, so the +`init` template and every documented example are unaffected. + +Node also derives a `.ts` file's module format from the nearest package.json +`type`, so in a CommonJS project the template's `import { defineConfig }` line +is a syntax error — the bundled TypeScript compiler used to hide this. So +`srcpack.config.mts` joins `searchPlaces`, and `init` writes it whenever the +project is not `"type": "module"`. `.mts` is unconditionally ESM and loads +either way; `.ts` stays the default for ESM projects because it is the name +the docs use. + +The test suite runs on Bun, which loads either extension regardless of package +type and so cannot see this class of failure. CI installs the packed tarball +into a CommonJS project and runs the CLI under Node to cover it. + +Both EOL runtimes are dropped in one step, so the next floor bump can wait for +a real forcing function rather than following each dependency's minor releases. diff --git a/docs/adr/index.md b/docs/adr/index.md new file mode 100644 index 0000000..4a59ee7 --- /dev/null +++ b/docs/adr/index.md @@ -0,0 +1,13 @@ +# Architecture Decisions + +Records of the decisions that shaped srcpack: what was chosen, what was +rejected, and the reasoning at the time. Written when the decision is made, +so they capture the trade-offs rather than a tidied-up version of them. + +A record is never rewritten once accepted. When a decision is reversed, a new +record supersedes it. + +| ADR | Decision | Status | +| ------------------------------------ | -------------------------------------------- | ------------------- | +| [001](./001-git-source-tokens.md) | `git:` source tokens in the pattern language | Accepted 2026-08-15 | +| [002](./002-minimum-node-version.md) | Node 22.18 as the minimum runtime | Accepted 2026-08-15 | diff --git a/docs/cli.md b/docs/cli.md index b027e67..c6b5c63 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -94,6 +94,25 @@ yarn dlx srcpack web api ::: +**Changed files only:** + +```sh +npx srcpack --staged # staged changes +npx srcpack --dirty # staged + unstaged + untracked +npx srcpack --since main # everything you changed since main +``` + +These build a one-off bundle from the current change set and need no config +file — handy for handing a work-in-progress to an LLM. The bundle is named +after the flag (`.srcpack/staged.txt`), other bundles in `outDir` are left +alone, and nothing is written when there are no changes. + +Ad-hoc bundles stay local: they are never uploaded, even with Google Drive +configured. Declare a named bundle to publish changes. + +For a permanent version with review instructions attached, put a +[git source](./configuration.md#git-sources-git-prefix) in your config instead. + ### `srcpack init` Create a `srcpack.config.ts` interactively. @@ -144,16 +163,19 @@ yarn dlx srcpack login ::: -Opens a browser to authorize access. Tokens are stored in `~/.config/srcpack/credentials.json`. +Opens a browser to authorize access. Tokens are stored in `~/.config/srcpack/credentials.json`, readable only by you. ## Options -| Option | Description | -| ------------- | ------------------------------------- | -| `--dry-run` | Preview bundles without writing files | -| `--no-upload` | Bundle only, skip upload | -| `--help` | Show help | -| `--version` | Show version | +| Option | Description | +| --------------- | ---------------------------------------------- | +| `--staged` | Bundle staged changes only | +| `--dirty` | Bundle staged, unstaged, and untracked changes | +| `--since ` | Bundle changes since `` | +| `--dry-run` | Preview bundles without writing files | +| `--no-upload` | Bundle only, skip upload | +| `--help` | Show help | +| `--version` | Show version | ## Examples @@ -220,7 +242,11 @@ yarn dlx srcpack --no-upload Srcpack searches for config in order: 1. `srcpack.config.ts` -2. `srcpack.config.js` -3. `srcpack` field in `package.json` +2. `srcpack.config.mts` +3. `srcpack.config.js` +4. `srcpack` field in `package.json` Searches from current directory up to filesystem root. + +`srcpack init` writes `.ts` in an ESM project and `.mts` otherwise — see +[Configuration](./configuration.md#config-file-format). diff --git a/docs/configuration.md b/docs/configuration.md index 00ff00c..f7ad896 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,8 +3,27 @@ Srcpack looks for configuration in the following order: 1. `srcpack.config.ts` (recommended) -2. `srcpack.config.js` -3. `srcpack` field in `package.json` +2. `srcpack.config.mts` +3. `srcpack.config.js` +4. `srcpack` field in `package.json` + +## Config File Format + +Node decides a `.ts` file's module format from the nearest `package.json`, so +in a CommonJS project — the `npm init` default — the `import` line in a +`.ts` config fails to parse. Use `.mts` there: it is unconditionally ESM and +loads in both kinds of project. + +`srcpack init` picks the right extension for you. If you are writing the file +by hand: + +| Your `package.json` | Use | +| ------------------------ | -------------------- | +| `"type": "module"` | `srcpack.config.ts` | +| no `type`, or `commonjs` | `srcpack.config.mts` | + +Config files are type-stripped, not compiled, so they must use erasable syntax +— type annotations and `import type` are fine, `enum` and `namespace` are not. ## Basic Structure @@ -61,6 +80,13 @@ export default defineConfig({ }); ``` +`outDir` is emptied before bundling when it sits inside the project root, so +give srcpack a directory of its own. Pointing it at the root itself (`"."`) +is refused rather than emptied — that would delete the project. + +Emptying only happens on a full run. `srcpack web` leaves the bundles it isn't +building in place, since it has no way to tell which of them are stale. + ## Bundle Definitions Each bundle can be defined in three ways: @@ -116,6 +142,7 @@ Patterns follow standard glob syntax with special prefixes: | `!**/*.test.ts` | Exclude test files | | `+**/*.local.md` | Force-include, bypass `.gitignore` | | `{src,lib}/**/*` | Files in `src/` or `lib/` | +| `git:staged` | Staged changes (see below) | ### Force-Include (`+` prefix) @@ -130,15 +157,59 @@ bundles: { } ``` +### Git Sources (`git:` prefix) + +A pattern can name a set of changed files instead of a glob: + +| Source | Files | +| --------------- | ----------------------------------------------------- | +| `git:staged` | Staged changes (index vs `HEAD`) | +| `git:unstaged` | Unstaged changes to tracked files (worktree vs index) | +| `git:untracked` | New files not ignored by git | +| `git:dirty` | All three combined | +| `git:` | Changes vs `` (e.g. `git:main`, `git:HEAD~3`) | + +```ts +bundles: { + review: { + include: ["git:staged", "!bun.lock"], + prompt: "Review these changes for correctness.", + }, +} +``` + +Git sources mix freely with each other, with globs, and with `!` exclusions: + +```ts +bundles: { + pr: ["git:main", "git:untracked", "docs/architecture.md", "!**/*.snap"], +} +``` + +Notes: + +- **A git source picks _which_ files to bundle; content always comes from the worktree.** If a file is staged and then edited again, `git:staged` bundles the current version on disk, not the staged blob. +- **`git:` compares against the merge base**, so a branch that has fallen behind `main` still reports only your own changes. Uncommitted edits to tracked files are included; untracked files are not — add `git:untracked` for those. Ranges (`git:main...HEAD`, `git:HEAD~3..HEAD`) pass through to git verbatim and cover committed changes only. Requires git 2.30+. +- **Deleted files are skipped** — there is nothing left to read. Same for binary files and submodules. +- **Symlinks are skipped**, in git sources and globs alike. A tracked link like `notes.txt -> ~/.ssh/id_rsa` would otherwise pull a file from outside the project into a bundle you might upload. Point a pattern at the real path instead. +- **`.gitignore` does not apply.** A file tracked despite `.gitignore` (force-added) is included; an ignored file is never reported by git in the first place. +- **A branch named `staged` is shadowed** by the named source. Use `git:refs/heads/staged` to disambiguate. +- **An empty result writes no file**, and clears a stale one from a previous run, so a bundle never holds changes you've since committed. A custom `outfile` outside `outDir` is left alone. +- `!git:...` and `+git:...` are errors: exclusion has no clear meaning, and force-include is already implied. + ## Automatic Exclusions -Srcpack automatically excludes: +Srcpack skips: -- Files matching `.gitignore` patterns -- Binary files (images, fonts, compiled assets) -- `node_modules/` -- `.git/` -- Lock files (`package-lock.json`, `yarn.lock`, etc.) +- Files matching `.gitignore` — including `node_modules/`, build output, and + secrets, since those are already ignored in any normal project +- Binary files (images, fonts, compiled assets), detected by content +- Symlinks, so a link can't pull in a file from outside the project +- Its own output — `outDir` and every configured `outfile`. Otherwise a rerun + would bundle the previous run's file, nesting it again each time. + +Everything else matched by a pattern is included, so exclude what you don't +want explicitly: `["src/**/*", "!bun.lock"]`. ## Examples @@ -211,9 +282,7 @@ Configure cloud upload destinations. See [Google Drive Upload](/upload) for setu ```ts export default defineConfig({ - bundles: { - /* ... */ - }, + bundles: {/* ... */}, upload: { provider: "gdrive", folderId: "1ABC...", diff --git a/docs/getting-started.md b/docs/getting-started.md index 3988207..e6caca4 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -4,7 +4,7 @@ Bundle your codebase into LLM-optimized context files. Get precise, grounded ans ## Prerequisites -- Node.js 20+ or Bun +- Node.js 22.18+ or Bun - A codebase you want to share with AI ## Quick Start @@ -159,6 +159,24 @@ export default defineConfig({ }); ``` +### Review Bundle + +Bundle what you changed instead of a fixed set of paths: + +```ts +export default defineConfig({ + bundles: { + review: { + include: ["git:staged", "!bun.lock"], + prompt: "Review these changes for correctness.", + }, + }, +}); +``` + +See [Git sources](./configuration.md#git-sources-git-prefix) for `git:dirty`, +`git:main`, and the rest. + ## CLI Reference ::: code-group @@ -166,6 +184,7 @@ export default defineConfig({ ```sh [npm] npx srcpack # Bundle all npx srcpack web api # Bundle specific bundles only +npx srcpack --staged # Bundle staged changes (no config needed) npx srcpack --dry-run # Preview without writing npx srcpack --no-upload # Skip upload even if configured ``` @@ -173,6 +192,7 @@ npx srcpack --no-upload # Skip upload even if configured ```sh [bun] bunx srcpack # Bundle all bunx srcpack web api # Bundle specific bundles only +bunx srcpack --staged # Bundle staged changes (no config needed) bunx srcpack --dry-run # Preview without writing bunx srcpack --no-upload # Skip upload even if configured ``` @@ -180,6 +200,7 @@ bunx srcpack --no-upload # Skip upload even if configured ```sh [pnpm] pnpm dlx srcpack # Bundle all pnpm dlx srcpack web api # Bundle specific bundles only +pnpm dlx srcpack --staged # Bundle staged changes (no config needed) pnpm dlx srcpack --dry-run # Preview without writing pnpm dlx srcpack --no-upload # Skip upload even if configured ``` @@ -187,6 +208,7 @@ pnpm dlx srcpack --no-upload # Skip upload even if configured ```sh [yarn] yarn dlx srcpack # Bundle all yarn dlx srcpack web api # Bundle specific bundles only +yarn dlx srcpack --staged # Bundle staged changes (no config needed) yarn dlx srcpack --dry-run # Preview without writing yarn dlx srcpack --no-upload # Skip upload even if configured ``` diff --git a/docs/index.md b/docs/index.md index 38513ea..07bcd8a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,7 +24,10 @@ features: - icon: 📑 title: Indexed Output details: File list with line numbers at top. LLMs can reference exact locations. + - icon: 🔀 + title: Git-Aware + details: Bundle what you changed. srcpack --staged works with no config at all. - icon: 🔒 title: Safe Defaults - details: Respects .gitignore. Excludes binaries and secrets. Zero config to start. + details: Respects .gitignore, so secrets stay out. Skips binaries. Zero config to start. --- diff --git a/docs/upload.md b/docs/upload.md index 31b0446..5878051 100644 --- a/docs/upload.md +++ b/docs/upload.md @@ -163,9 +163,7 @@ For CI/CD or shared configs, use environment variables: ```ts export default defineConfig({ - bundles: { - /* ... */ - }, + bundles: {/* ... */}, upload: { provider: "gdrive", folderId: process.env.GDRIVE_FOLDER_ID, diff --git a/package.json b/package.json index 25fc89b..d4dd3c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "srcpack", - "version": "0.1.15", + "version": "0.2.0", "description": "Zero-config CLI for bundling code into LLM-optimized context files", "keywords": [ "llm", @@ -42,7 +42,7 @@ "url": "https://github.com/kriasoft/srcpack/issues" }, "engines": { - "node": ">=18.0.0" + "node": "^22.18.0 || >=24" }, "type": "module", "types": "./dist/index.d.ts", @@ -73,28 +73,26 @@ "test:watch": "bun test tests/unit/ tests/e2e/ --watch", "docs:dev": "vitepress dev", "docs:build": "vitepress build", - "docs:preview": "vitepress preview", - "docs:deploy": "gh-pages -d .vitepress/dist" + "docs:preview": "vitepress preview" }, "dependencies": { - "@clack/prompts": "^0.11.0", - "@googleapis/drive": "^20.0.0", - "cosmiconfig": "^9.0.0", + "@clack/prompts": "^1.7.0", + "@googleapis/drive": "^21.0.0", + "cosmiconfig": "^10.0.0", "fast-glob": "^3.3.3", - "google-auth-library": "^10.5.0", - "ignore": "^7.0.5", - "oauth-callback": "^1.2.5", - "ora": "^9.1.0", - "picomatch": "^4.0.2", - "zod": "^4.3.5" + "google-auth-library": "10.5.0", + "ignore": "^7.0.6", + "oauth-callback": "^2.2.0", + "ora": "^9.4.1", + "picomatch": "^4.0.5", + "zod": "^4.4.3" }, "devDependencies": { - "@types/bun": "^1.3.6", - "@types/picomatch": "^4.0.2", - "gh-pages": "^6.3.0", - "prettier": "^3.8.1", - "typescript": "^5.9.3", - "vitepress": "^2.0.0-alpha.15", - "vitepress-plugin-llms": "^1.10.0" + "@types/bun": "^1.3.14", + "@types/picomatch": "^4.0.3", + "prettier": "^3.9.6", + "typescript": "^6.0.3", + "vitepress": "^2.0.0-alpha.19", + "vitepress-plugin-llms": "^1.13.5" } } diff --git a/src/bundle.ts b/src/bundle.ts index 49a815f..f19d771 100644 --- a/src/bundle.ts +++ b/src/bundle.ts @@ -1,24 +1,46 @@ // SPDX-License-Identifier: MIT -import { open, readFile, stat } from "node:fs/promises"; -import { join } from "node:path"; +import { lstat, open, readFile } from "node:fs/promises"; +import { isAbsolute, join, resolve, sep } from "node:path"; import { glob } from "fast-glob"; import picomatch from "picomatch"; import ignore, { type Ignore } from "ignore"; -import { expandPath, type BundleConfigInput } from "./config.ts"; +import { ConfigError, expandPath, type BundleConfigInput } from "./config.ts"; +import { isGitSource, resolveGitSource } from "./git.ts"; // Binary file detection: check first 8KB for null bytes (same heuristic as git) const BINARY_CHECK_SIZE = 8192; -async function isBinary(filePath: string): Promise { - const stats = await stat(filePath); - if (stats.size === 0) return false; +/** + * Whether a path can be read into a bundle: an existing regular text file. + * Globs only yield files, but git can name a submodule directory or a file + * deleted from the worktree after it was listed. + * + * `lstat` deliberately does not follow symlinks: a tracked link such as + * `notes.txt -> ~/.ssh/id_rsa` would otherwise bundle a file from outside the + * project under an innocuous name. Point a pattern at the real path instead. + */ +async function isBundleable(filePath: string): Promise { + let stats; + try { + stats = await lstat(filePath); + } catch { + return false; + } + if (!stats.isFile()) return false; + if (stats.size === 0) return true; - const fd = await open(filePath, "r"); + // Racy against deletion between lstat and open, so failure means "skip" + let fd; + try { + fd = await open(filePath, "r"); + } catch { + return false; + } try { const buffer = Buffer.alloc(Math.min(stats.size, BINARY_CHECK_SIZE)); await fd.read(buffer, 0, buffer.length, 0); - return buffer.includes(0); + return !buffer.includes(0); } finally { await fd.close(); } @@ -41,7 +63,20 @@ export interface BundleResult { * - Regular patterns: included, filtered by .gitignore * - `!pattern`: excluded from results * - `+pattern`: force-included, bypasses .gitignore + * + * `git:` sources are include-only: `!` has no clear meaning for them, and `+` + * is redundant since they already bypass .gitignore. */ +/** + * Prepare a config pattern for matching: expand `~/`, then force posix + * separators. fast-glob and picomatch require them, but `~/` expansion and + * hand-written Windows paths produce backslashes. + */ +function toPattern(pattern: string): string { + const expanded = expandPath(pattern); + return sep === "\\" ? expanded.replaceAll("\\", "/") : expanded; +} + function normalizePatterns(config: BundleConfigInput): { include: string[]; exclude: string[]; @@ -65,11 +100,23 @@ function normalizePatterns(config: BundleConfigInput): { for (const p of patterns) { if (p.startsWith("!")) { - exclude.push(p.slice(1)); + exclude.push(toPattern(p.slice(1))); } else if (p.startsWith("+")) { - force.push(p.slice(1)); + force.push(toPattern(p.slice(1))); } else { - include.push(p); + include.push(toPattern(p)); + } + } + + for (const [prefix, prefixed] of [ + ["!", exclude], + ["+", force], + ] as const) { + const misused = prefixed.find(isGitSource); + if (misused) { + throw new ConfigError( + `Git sources cannot use the "${prefix}" prefix: "${prefix}${misused}"`, + ); } } @@ -164,79 +211,96 @@ async function loadGitignore(cwd: string): Promise { /** * Check if a glob pattern references paths outside cwd. * Patterns traversing to parent directories start with ../ (or ./../). + * Absolute paths are also external. */ function isExternalPattern(pattern: string): boolean { + // e.g. from ~/xxx expansion; isAbsolute also catches Windows drive letters + if (isAbsolute(pattern)) return true; // Handle redundant ./ prefix (e.g., ./../other) const normalized = pattern.startsWith("./") ? pattern.slice(2) : pattern; return normalized.startsWith("../"); } +/** + * Whether a path is one srcpack writes. `outputs` holds absolute paths of + * files or directories; a directory covers everything beneath it. + */ +function isOwnOutput(filePath: string, outputs: string[]): boolean { + return outputs.some( + (out) => filePath === out || filePath.startsWith(out + sep), + ); +} + /** * Resolve bundle config to a list of file paths. * - Regular patterns respect .gitignore * - Force patterns (+prefix) bypass .gitignore - * - Exclude patterns (!prefix) filter both - * - External patterns (../) skip .gitignore entirely + * - Exclude patterns (!prefix) filter everything, including git sources + * - External patterns (`../`, absolute) skip .gitignore entirely + * - `git:` sources yield concrete paths and skip .gitignore (already tracked, + * or reported by git only when not ignored) + * + * `outputs` names absolute paths srcpack writes (outDir, custom outfiles). + * They are never bundled: a rerun would otherwise bundle the previous run's + * output, nesting it one level deeper every time. */ export async function resolvePatterns( config: BundleConfigInput, cwd: string, + outputs: string[] = [], ): Promise { const { include, exclude, force } = normalizePatterns(config); const excludeMatchers = exclude.map((p) => picomatch(p)); - const { ignore: gitignore, globPatterns } = await loadGitignore(cwd); const files = new Set(); + // Dedupe by absolute path, not by pattern text: an absolute pattern and a + // relative one can name the same file, which would bundle it twice. + const seen = new Set(); + + // Absolute patterns (from `~/` or `/`) make fast-glob return absolute paths, + // so resolve rather than join — `join(cwd, "/abs")` would mangle them. + const add = async (candidates: string[]) => { + for (const path of candidates) { + if (isExcluded(path, excludeMatchers)) continue; + const absolute = resolve(cwd, path); + if (seen.has(absolute)) continue; + if (isOwnOutput(absolute, outputs)) continue; + if (await isBundleable(absolute)) { + seen.add(absolute); + files.add(path); + } + } + }; - // Split patterns into internal (within cwd) and external (../ prefixed) - const internalPatterns = include.filter((p) => !isExternalPattern(p)); - const externalPatterns = include.filter(isExternalPattern); + for (const source of include.filter(isGitSource)) { + await add(await resolveGitSource(source, cwd)); + } + + const globs = include.filter((p) => !isGitSource(p)); - // Internal patterns: respect .gitignore + // Internal patterns (within cwd): respect .gitignore + const internalPatterns = globs.filter((p) => !isExternalPattern(p)); if (internalPatterns.length > 0) { + const { ignore: gitignore, globPatterns } = await loadGitignore(cwd); const matches = await glob(internalPatterns, { cwd, onlyFiles: true, dot: true, ignore: globPatterns, }); - for (const match of matches) { - if (!isExcluded(match, excludeMatchers) && !gitignore.ignores(match)) { - const fullPath = join(cwd, match); - if (!(await isBinary(fullPath))) { - files.add(match); - } - } - } + await add(matches.filter((m) => !gitignore.ignores(m))); } // External patterns: skip .gitignore (it doesn't apply outside cwd) + const externalPatterns = globs.filter(isExternalPattern); if (externalPatterns.length > 0) { - const matches = await glob(externalPatterns, { - cwd, - onlyFiles: true, - dot: true, - }); - for (const match of matches) { - if (!isExcluded(match, excludeMatchers)) { - const fullPath = join(cwd, match); - if (!(await isBinary(fullPath))) { - files.add(match); - } - } - } + await add( + await glob(externalPatterns, { cwd, onlyFiles: true, dot: true }), + ); } // Force includes: bypass .gitignore (no ignore patterns passed to glob) if (force.length > 0) { - const matches = await glob(force, { cwd, onlyFiles: true, dot: true }); - for (const match of matches) { - if (!isExcluded(match, excludeMatchers)) { - const fullPath = join(cwd, match); - if (!(await isBinary(fullPath))) { - files.add(match); - } - } - } + await add(await glob(force, { cwd, onlyFiles: true, dot: true })); } // Sort for deterministic output @@ -309,8 +373,7 @@ export async function createBundle( for (let i = 0; i < files.length; i++) { const filePath = files[i]!; - const fullPath = join(cwd, filePath); - const content = await readFile(fullPath, "utf-8"); + const content = await readFile(resolve(cwd, filePath), "utf-8"); const lines = countLines(content); // Separator takes 1 line, then content starts on next line @@ -423,14 +486,15 @@ async function resolvePrompt( } /** - * Bundle a single named bundle from config + * Bundle one config entry. `outputs` lists absolute paths srcpack writes, + * which are never bundled — see {@link resolvePatterns}. */ export async function bundleOne( - name: string, config: BundleConfigInput, cwd: string, + outputs: string[] = [], ): Promise { - const files = await resolvePatterns(config, cwd); + const files = await resolvePatterns(config, cwd, outputs); const includeIndex = getIncludeIndex(config); const prompt = await resolvePrompt(getPrompt(config), cwd); return createBundle(files, cwd, { includeIndex, prompt }); diff --git a/src/cli.ts b/src/cli.ts index 0479f41..a44f848 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,16 +1,18 @@ #!/usr/bin/env node // SPDX-License-Identifier: MIT -import { mkdir, readdir, rm, writeFile } from "node:fs/promises"; -import { dirname, isAbsolute, join, relative, resolve } from "node:path"; +import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises"; +import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path"; import ora from "ora"; import { bundleOne, type BundleResult } from "./bundle.ts"; import { ConfigError, loadConfig, + parseConfig, type BundleConfig, type UploadConfig, } from "./config.ts"; +import { GitError } from "./git.ts"; import { ensureAuthenticated, login, @@ -38,10 +40,10 @@ function plural(n: number, singular: string, pluralForm?: string): string { return n === 1 ? singular : (pluralForm ?? singular + "s"); } -function isOutDirInsideRoot(outDir: string, root: string): boolean { - const absoluteOutDir = isAbsolute(outDir) ? outDir : resolve(root, outDir); - const rel = relative(root, absoluteOutDir); - return !rel.startsWith("..") && !isAbsolute(rel); +function isInside(path: string, dir: string): boolean { + const rel = relative(dir, path); + // Compare against ".." as a whole segment — "..cache/x" is a child, not an escape + return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel); } /** @@ -63,9 +65,70 @@ async function emptyDirectory(dir: string, skip: string[] = []): Promise { ); } +/** + * One-off bundle from a `git:` source instead of a configured one. Needs no + * config file — reviewing what you just wrote is throwaway, not worth committing. + */ +interface AdHocBundle { + name: string; + patterns: string[]; +} + +const AD_HOC_FLAGS = ["--staged", "--dirty", "--since"] as const; + +function parseAdHocBundle(args: string[]): AdHocBundle | null { + const flags = AD_HOC_FLAGS.filter((flag) => args.includes(flag)); + + if (flags.length > 1) { + console.error(`Cannot combine ${flags.join(" and ")}.`); + process.exit(1); + } + + switch (flags[0]) { + case "--staged": + return { name: "staged", patterns: ["git:staged"] }; + case "--dirty": + return { name: "dirty", patterns: ["git:dirty"] }; + case "--since": { + const rev = args[args.indexOf("--since") + 1]; + if (!rev || rev.startsWith("-")) { + console.error("Missing revision: --since (e.g. --since main)"); + process.exit(1); + } + // A range pins both endpoints, so it would silently drop the uncommitted + // work --since promises. Ranges belong in a config `git:` source. + if (rev.includes("..")) { + console.error( + `--since takes a revision, not a range: "${rev}". Use a git: source in your config for ranges.`, + ); + process.exit(1); + } + // `git diff` can't see untracked files, but a new file written on this + // branch is part of "what changed since " + return { name: "since", patterns: [`git:${rev}`, "git:untracked"] }; + } + default: + return null; + } +} + +/** Resolves to the package root from both `src/cli.ts` and `dist/cli.js`. */ +async function readVersion(): Promise { + const pkg = await readFile( + new URL("../package.json", import.meta.url), + "utf-8", + ); + return (JSON.parse(pkg) as { version: string }).version; +} + async function main() { const args = process.argv.slice(2); + if (args.includes("--version") || args.includes("-v")) { + console.log(await readVersion()); + return; + } + if (args.includes("--help") || args.includes("-h")) { console.log(` srcpack - Bundle and upload tool @@ -73,27 +136,34 @@ srcpack - Bundle and upload tool Usage: npx srcpack Bundle all, upload if configured npx srcpack web api Bundle specific bundles only + npx srcpack --staged Bundle staged changes (no config needed) npx srcpack --dry-run Preview bundles without writing files npx srcpack --no-upload Bundle only, skip upload npx srcpack init Interactive config setup npx srcpack login Authenticate with Google Drive Options: + --staged Bundle staged changes only + --dirty Bundle staged, unstaged, and untracked changes + --since Bundle changes since (e.g. --since main) --dry-run Preview bundles without writing files --emptyOutDir Empty output directory before bundling --no-emptyOutDir Keep existing files in output directory --no-upload Skip uploading to cloud storage -h, --help Show this help message + -v, --version Show version `); return; } - if (args.includes("init")) { + // Only in first position: elsewhere the word is a bundle name or a revision, + // and `--since init` must diff against the `init` branch, not run the wizard. + if (args[0] === "init") { await runInit(); return; } - if (args.includes("login")) { + if (args[0] === "login") { await runLogin(); return; } @@ -106,28 +176,41 @@ Options: : args.includes("--no-emptyOutDir") ? false : undefined; - const subcommands = ["init", "login"]; + const adHoc = parseAdHocBundle(args); + const sinceIndex = args.indexOf("--since"); + const sinceValueIndex = sinceIndex === -1 ? -1 : sinceIndex + 1; const requestedBundles = args.filter( - (arg) => !arg.startsWith("-") && !subcommands.includes(arg), + (arg, i) => !arg.startsWith("-") && i !== sinceValueIndex, ); - const config = await loadConfig(); + if (adHoc && requestedBundles.length) { + console.error(`Cannot combine --${adHoc.name} with named bundles.`); + process.exit(1); + } + + let config = await loadConfig(); if (!config) { - console.error( - "No configuration found. Run `npx srcpack init` to create one.", - ); - process.exit(1); + if (!adHoc) { + console.error( + "No configuration found. Run `npx srcpack init` to create one.", + ); + process.exit(1); + } + // Ad-hoc bundles are self-describing, so defaults are enough + config = parseConfig({ bundles: {} }); } + const bundles = adHoc ? { [adHoc.name]: adHoc.patterns } : config.bundles; + // Determine which bundles to process const bundleNames = requestedBundles.length ? requestedBundles - : Object.keys(config.bundles); + : Object.keys(bundles); // Validate requested bundle names exist for (const name of bundleNames) { - if (!(name in config.bundles)) { + if (!(name in bundles)) { console.error(`Unknown bundle: ${name}`); process.exit(1); } @@ -140,12 +223,17 @@ Options: const root = config.root; - // Resolve emptyOutDir: CLI flag > config > auto (true if inside root) - const outDirInsideRoot = isOutDirInsideRoot(config.outDir, root); - const emptyOutDir = emptyOutDirFlag ?? config.emptyOutDir ?? outDirInsideRoot; + // Resolve emptyOutDir: CLI flag > config > auto (true if inside root). + // Ad-hoc runs never empty by default — they shouldn't delete configured bundles. + const outDirPath = resolve(root, config.outDir); + const outDirInsideRoot = isInside(outDirPath, root); + const emptyOutDir = + emptyOutDirFlag ?? + (adHoc ? false : (config.emptyOutDir ?? outDirInsideRoot)); // Warn if outDir is outside root and emptyOutDir is not explicitly set if ( + !adHoc && !outDirInsideRoot && emptyOutDirFlag === undefined && config.emptyOutDir === undefined @@ -156,14 +244,31 @@ Options: ); } - // Empty outDir before bundling (unless dry-run) - if (emptyOutDir && !dryRun) { - const outDirPath = isAbsolute(config.outDir) - ? config.outDir - : resolve(root, config.outDir); + // `outDir: "."` resolves to the project root, where emptying deletes the + // whole project — sources, config and all. Refuse rather than warn. + const outDirHoldsRoot = isInside(root, outDirPath); + if (emptyOutDir && outDirHoldsRoot) { + throw new ConfigError( + `Refusing to empty outDir "${config.outDir}": it contains the project root. ` + + "Use a subdirectory, or set emptyOutDir: false.", + ); + } + + // Empty outDir before bundling (unless dry-run). Only for a full run: a named + // subset can't tell what is stale, so `srcpack web` must not delete api.txt. + if (emptyOutDir && !dryRun && requestedBundles.length === 0) { await emptyDirectory(outDirPath, [".git"]); } + // srcpack never bundles what srcpack writes. Every configured outfile is + // named explicitly; outDir covers stale bundles from renamed config entries + // too, but not when it holds the root — that would exclude the whole project. + const ownOutputs = Object.entries(config.bundles).map( + ([name, bundleConfig]) => + resolve(root, getOutfile(bundleConfig, name, config.outDir)), + ); + if (!outDirHoldsRoot) ownOutputs.push(outDirPath); + const outputs: BundleOutput[] = []; // Process all bundles with progress @@ -172,17 +277,19 @@ Options: color: "cyan", }).start(); - for (let i = 0; i < bundleNames.length; i++) { - const name = bundleNames[i]!; - bundleSpinner.text = `Bundling ${name}... (${i + 1}/${bundleNames.length})`; - const bundleConfig = config.bundles[name]!; - const result = await bundleOne(name, bundleConfig, root); - const outfile = getOutfile(bundleConfig, name, config.outDir); - outputs.push({ name, outfile, result }); + try { + for (let i = 0; i < bundleNames.length; i++) { + const name = bundleNames[i]!; + bundleSpinner.text = `Bundling ${name}... (${i + 1}/${bundleNames.length})`; + const bundleConfig = bundles[name]!; + const result = await bundleOne(bundleConfig, root, ownOutputs); + const outfile = getOutfile(bundleConfig, name, config.outDir); + outputs.push({ name, outfile, result }); + } + } finally { + bundleSpinner.stop(); } - bundleSpinner.stop(); - // Calculate column widths for aligned output const maxNameLen = Math.max(...outputs.map((o) => o.name.length)); const maxFilesLen = Math.max( @@ -210,6 +317,15 @@ Options: for (const entry of result.index) { console.log(` ${entry.path}`); } + } else if (fileCount === 0) { + // Drop a previous run's file so the bundle never goes stale, but only + // inside outDir — a custom outfile points at a location srcpack doesn't own + if (isInside(outPath, outDirPath)) { + await rm(outPath, { force: true }); + } + console.log( + ` ${nameCol} ${filesCol} ${plural(fileCount, "file")} ${linesCol} ${plural(lineCount, "line")} → skipped`, + ); } else { await mkdir(dirname(outPath), { recursive: true }); await writeFile(outPath, result.content); @@ -237,8 +353,10 @@ Options: `Bundled: ${outputs.length} ${bundleWord}, ${formatNumber(totalFiles)} ${fileWord}, ${formatNumber(totalLines)} ${lineWord}`, ); - // Handle upload if configured and not disabled - if (config.upload && !noUpload) { + // Ad-hoc bundles stay local: uploading work-in-progress to Drive is not + // what --staged asks for, and `upload.exclude` can't name a bundle the + // config doesn't declare. Configure a named bundle to publish changes. + if (config.upload && !noUpload && !adHoc) { const uploads = Array.isArray(config.upload) ? config.upload : [config.upload]; @@ -338,12 +456,14 @@ async function handleGdriveUpload( outputs: BundleOutput[], root: string, ): Promise { - // Filter out excluded bundles + // Filter out excluded bundles and empty ones (never written to disk) const excludeSet = new Set(uploadConfig.exclude ?? []); - const toUpload = outputs.filter((o) => !excludeSet.has(o.name)); + const toUpload = outputs.filter( + (o) => !excludeSet.has(o.name) && o.result.index.length > 0, + ); if (toUpload.length === 0) { - console.log("\nNo bundles to upload (all excluded)."); + console.log("\nNo bundles to upload."); return; } @@ -357,16 +477,18 @@ async function handleGdriveUpload( const results: UploadResult[] = []; - for (let i = 0; i < toUpload.length; i++) { - const output = toUpload[i]!; - const filePath = resolve(root, output.outfile); - uploadSpinner.text = `Uploading ${output.name}... (${i + 1}/${toUpload.length})`; - const result = await uploadFile(filePath, uploadConfig); - results.push(result); + try { + for (let i = 0; i < toUpload.length; i++) { + const output = toUpload[i]!; + const filePath = resolve(root, output.outfile); + uploadSpinner.text = `Uploading ${output.name}... (${i + 1}/${toUpload.length})`; + const result = await uploadFile(filePath, uploadConfig); + results.push(result); + } + } finally { + uploadSpinner.stop(); } - uploadSpinner.stop(); - // Print upload summary console.log(); const uploadWord = plural(results.length, "file"); @@ -385,6 +507,8 @@ async function handleGdriveUpload( if (error.error_description) { console.error(` ${error.error_description}`); } + // A failed upload must not report success — CI depends on the exit code + process.exitCode = 1; } else { throw error; } @@ -407,6 +531,9 @@ function getOutfile( } main().catch((err) => { - console.error(err); + // Config and git failures are user-facing; a stack trace only adds noise + console.error( + err instanceof ConfigError || err instanceof GitError ? err.message : err, + ); process.exit(1); }); diff --git a/src/config.ts b/src/config.ts index 02d8840..e8a68b0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -22,6 +22,15 @@ const PatternsSchema = z.union([ * Bundle configuration. Accepts a string pattern, array of patterns, or object. * Patterns prefixed with `!` are exclusions. Patterns prefixed with `+` force * inclusion (bypass .gitignore). + * + * A pattern may also be a git source instead of a glob: `git:staged`, + * `git:unstaged`, `git:untracked`, `git:dirty`, or `git:` (e.g. + * `git:main`, `git:HEAD~3`). + * + * @example + * ```ts + * bundles: { review: ["git:staged", "!bun.lock"] } + * ``` */ const BundleConfigSchema = z.union([ z.string().min(1), @@ -130,7 +139,8 @@ export function parseConfig(value: unknown): Config { const explorer = cosmiconfig("srcpack", { searchPlaces: [ - "srcpack.config.ts", // Primary: full TypeScript support with Bun + "srcpack.config.ts", // Primary: works in an ESM project ("type": "module") + "srcpack.config.mts", // Unconditionally ESM, so it also loads in CommonJS "srcpack.config.js", // Fallback for JS-only projects "package.json", // Zero-file option via "srcpack" field ], diff --git a/src/gdrive.ts b/src/gdrive.ts index 5b1b4da..9659027 100644 --- a/src/gdrive.ts +++ b/src/gdrive.ts @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT +import { spawn } from "node:child_process"; import { createReadStream } from "node:fs"; -import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { chmod, mkdir, readFile, writeFile } from "node:fs/promises"; import { homedir } from "node:os"; import { dirname, join, basename } from "node:path"; import { drive as createDrive, type drive_v3 } from "@googleapis/drive"; +// Exact-pinned in package.json: googleapis-common pins google-auth-library to a +// single version, and createDrive() only accepts that copy's OAuth2Client. A +// caret range resolves a second copy whose private fields fail to structurally +// match. Bump this in lockstep with @googleapis/drive. import { OAuth2Client } from "google-auth-library"; import { getAuthCode, OAuthError } from "oauth-callback"; import type { UploadConfig } from "./config.ts"; @@ -51,15 +56,21 @@ async function readCredentials(): Promise { } async function writeCredentials(creds: CredentialsFile): Promise { - await mkdir(dirname(CREDENTIALS_PATH), { recursive: true }); - await writeFile(CREDENTIALS_PATH, JSON.stringify(creds, null, 2)); + // A refresh token grants lasting access to the user's Drive, so keep it + // owner-only. `mode` applies at creation; chmod also fixes files written + // by an older version with the default 0644. + await mkdir(dirname(CREDENTIALS_PATH), { recursive: true, mode: 0o700 }); + await writeFile(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), { + mode: 0o600, + }); + await chmod(CREDENTIALS_PATH, 0o600); } /** * Loads stored tokens for a specific OAuth client. * Returns null if no tokens exist or they cannot be read. */ -export async function loadTokens(config: UploadConfig): Promise { +async function loadTokens(config: UploadConfig): Promise { const creds = await readCredentials(); return creds.gdrive?.[config.clientId] ?? null; } @@ -74,17 +85,6 @@ async function saveTokens(tokens: Tokens, config: UploadConfig): Promise { await writeCredentials(creds); } -/** - * Removes stored tokens for a specific OAuth client. - */ -export async function clearTokens(config: UploadConfig): Promise { - const creds = await readCredentials(); - if (creds.gdrive?.[config.clientId]) { - delete creds.gdrive[config.clientId]; - await writeCredentials(creds); - } -} - /** * Checks if tokens are expired or about to expire (within 5 minutes). */ @@ -134,9 +134,7 @@ async function refreshAccessToken( * Gets valid tokens, refreshing if necessary. * Returns null if no tokens exist or refresh fails. */ -export async function getValidTokens( - config: UploadConfig, -): Promise { +async function getValidTokens(config: UploadConfig): Promise { const tokens = await loadTokens(config); if (!tokens) return null; @@ -151,6 +149,23 @@ export async function getValidTokens( return tokens; } +/** + * Opens the consent page in the default browser. oauth-callback made launching + * opt-in in v2 and swallows launcher errors, so the URL is printed as well — + * otherwise a headless machine waits out the timeout with nothing on screen. + */ +function launchBrowser(url: string): void { + console.log(`If the browser does not open, visit:\n${url}`); + const isWindows = process.platform === "win32"; + const command = isWindows + ? "cmd" + : process.platform === "darwin" + ? "open" + : "xdg-open"; + const args = isWindows ? ["/c", "start", "", url] : [url]; + spawn(command, args, { stdio: "ignore", detached: true }).unref(); +} + /** * Performs OAuth login flow - opens browser for user consent. * Stores tokens on success for future use. @@ -170,6 +185,7 @@ export async function login(config: UploadConfig): Promise { const result = await getAuthCode({ authorizationUrl: authUrl, + launch: launchBrowser, port: 3000, timeout: 300000, // 5 minutes }); @@ -245,6 +261,15 @@ function createDriveClient( return createDrive({ version: "v3", auth }); } +/** + * Escape a value for a single-quoted Drive query term. An unescaped quote + * changes what the query matches, so `notes'.txt` could resolve to an + * unrelated file — which the caller then overwrites. + */ +export function escapeQueryValue(value: string): string { + return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); +} + /** * Finds a file by name in a specific folder (or root). * Returns the file ID if found, null otherwise. @@ -254,8 +279,8 @@ async function findFile( name: string, folderId?: string, ): Promise { - const parent = folderId ?? "root"; - const query = `name = '${name}' and '${parent}' in parents and trashed = false`; + const parent = escapeQueryValue(folderId ?? "root"); + const query = `name = '${escapeQueryValue(name)}' and '${parent}' in parents and trashed = false`; const res = await drive.files.list({ q: query, @@ -324,19 +349,4 @@ export async function uploadFile( }; } -/** - * Uploads multiple files to Google Drive. - */ -export async function uploadFiles( - filePaths: string[], - config: UploadConfig, -): Promise { - const results: UploadResult[] = []; - for (const filePath of filePaths) { - const result = await uploadFile(filePath, config); - results.push(result); - } - return results; -} - export { OAuthError }; diff --git a/src/git.ts b/src/git.ts new file mode 100644 index 0000000..ff156a7 --- /dev/null +++ b/src/git.ts @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: MIT + +import { execFile } from "node:child_process"; +import { promisify } from "node:util"; + +const execFileAsync = promisify(execFile); + +/** Marks a pattern as a git source rather than a glob. */ +const GIT_PREFIX = "git:"; + +/** Added, Copied, Modified, Renamed — the states that leave a readable file. */ +const DIFF_FILTER = "--diff-filter=ACMR"; + +/** Large change sets can exceed Node's 1MB default. */ +const MAX_BUFFER = 32 * 1024 * 1024; + +export class GitError extends Error { + constructor(message: string) { + super(message); + this.name = "GitError"; + } +} + +export function isGitSource(pattern: string): boolean { + return pattern.startsWith(GIT_PREFIX); +} + +async function isRepository(cwd: string): Promise { + try { + await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd }); + return true; + } catch { + return false; + } +} + +/** + * Run git and split its NUL-terminated path list. + * `-z` avoids git's path quoting for non-ASCII and unusual filenames. + */ +async function run(args: string[], cwd: string): Promise { + let stdout: string; + try { + ({ stdout } = await execFileAsync("git", args, { + cwd, + encoding: "utf-8", + maxBuffer: MAX_BUFFER, + })); + } catch (error) { + const { code, stderr, message } = error as { + code?: string; + stderr?: string; + message?: string; + }; + if (code === "ENOENT") { + throw new GitError("git not found (required by `git:` patterns)"); + } + // Outside a repository `git diff` falls back to --no-index and reports a + // usage error, so check for the real cause before surfacing stderr. + if (!(await isRepository(cwd))) { + throw new GitError(`Not a git repository: ${cwd}`); + } + // stderr is empty when the process was killed (maxBuffer, signal), so fall + // back to the Node error rather than an opaque "failed" + throw new GitError( + stderr?.trim() || message?.trim() || `git ${args.join(" ")} failed`, + ); + } + return stdout.split("\0").filter(Boolean); +} + +/** + * Resolve a `git:` source to worktree-relative paths. + * + * - `git:staged` — index vs HEAD + * - `git:unstaged` — worktree vs index (tracked files only) + * - `git:untracked` — new files not ignored by git + * - `git:dirty` — union of the three + * - `git:` — worktree vs the merge base of `` and HEAD, so a + * diverged branch reports only your own changes. Ranges pass through verbatim. + * + * `--relative` scopes results to `cwd` and makes them relative to it, matching + * how glob patterns resolve. + */ +export async function resolveGitSource( + pattern: string, + cwd: string, +): Promise { + const source = pattern.slice(GIT_PREFIX.length); + + if (!source) { + throw new GitError( + `Empty git source in "${pattern}". Expected git:staged, git:unstaged, git:untracked, git:dirty, or git:.`, + ); + } + // git would parse a leading dash as a flag + if (source.startsWith("-")) { + throw new GitError( + `Invalid git source "${pattern}": revision starts with "-".`, + ); + } + + const diff = (...args: string[]) => + run( + ["diff", "--name-only", DIFF_FILTER, "--relative", "-z", ...args, "--"], + cwd, + ); + + switch (source) { + case "staged": + return diff("--cached"); + case "unstaged": + return diff(); + case "untracked": + return run(["ls-files", "--others", "--exclude-standard", "-z"], cwd); + case "dirty": { + const sets = await Promise.all([ + resolveGitSource("git:staged", cwd), + resolveGitSource("git:unstaged", cwd), + resolveGitSource("git:untracked", cwd), + ]); + return [...new Set(sets.flat())]; + } + default: + // A range already names both endpoints; a single rev gets merge-base + // treatment, which is a no-op for ancestors like HEAD~3. + return source.includes("..") + ? diff(source) + : diff("--merge-base", source); + } +} diff --git a/src/init.ts b/src/init.ts index 15f563a..c4480ae 100644 --- a/src/init.ts +++ b/src/init.ts @@ -5,21 +5,38 @@ import { appendFile, readFile, writeFile } from "node:fs/promises"; import { existsSync } from "node:fs"; import { join } from "node:path"; -const CONFIG_FILE = "srcpack.config.ts"; - type Bundle = { name: string; include: string[]; }; +/** + * Node decides a `.ts` file's module format from the nearest package.json + * `type`, so the generated config's `import` line is a syntax error in a + * CommonJS project. `.mts` is unconditionally ESM and loads in both. + */ +export function configFileName(packageType: string | undefined): string { + return packageType === "module" ? "srcpack.config.ts" : "srcpack.config.mts"; +} + +async function readPackageType(cwd: string): Promise { + try { + const pkg = await readFile(join(cwd, "package.json"), "utf-8"); + return (JSON.parse(pkg) as { type?: string }).type; + } catch { + return undefined; // No package.json, or unreadable: assume CommonJS + } +} + export async function runInit(): Promise { const cwd = process.cwd(); - const configPath = join(cwd, CONFIG_FILE); + const configFile = configFileName(await readPackageType(cwd)); + const configPath = join(cwd, configFile); - p.intro("Create srcpack.config.ts"); + p.intro(`Create ${configFile}`); if (existsSync(configPath)) { - p.log.warn(`${CONFIG_FILE} already exists`); + p.log.warn(`${configFile} already exists`); const overwrite = await p.confirm({ message: "Overwrite existing config?", initialValue: false, @@ -75,7 +92,7 @@ export async function runInit(): Promise { // Add output directory to .gitignore await addToGitignore(cwd, outDirValue); - p.outro(`Created ${CONFIG_FILE}`); + p.outro(`Created ${configFile}`); } async function promptBundle( @@ -86,7 +103,7 @@ async function promptBundle( message: isFirst ? "Bundle name:" : "Next bundle name:", placeholder: "api", validate: (value) => { - if (!value.trim()) return "Name is required"; + if (!value?.trim()) return "Name is required"; if (!/^[a-z][a-z0-9-]*$/.test(value)) { return "Use lowercase alphanumeric characters and hyphens"; } @@ -102,7 +119,7 @@ async function promptBundle( message: "Include patterns (comma-separated):", placeholder: "src/**/*", validate: (value) => { - if (!value.trim()) return "At least one pattern is required"; + if (!value?.trim()) return "At least one pattern is required"; }, }); @@ -116,17 +133,23 @@ async function promptBundle( return { name: name.trim(), include }; } -function generateConfig(bundles: Bundle[], outDir: string): string { +/** + * Render the config file. Every value goes through `JSON.stringify` so a + * backslash or quote can't corrupt the output — `"src\**\*"` would otherwise + * parse as `src***`, a pattern that matches nothing. + */ +export function generateConfig(bundles: Bundle[], outDir: string): string { const bundleEntries = bundles.map(({ name, include }) => { - const value = - include.length === 1 ? `"${include[0]}"` : JSON.stringify(include); - return ` ${name}: ${value},`; + const value = JSON.stringify(include.length === 1 ? include[0] : include); + // Names may contain hyphens, which a bare object key may not + const key = /^[a-z][a-z0-9]*$/.test(name) ? name : JSON.stringify(name); + return ` ${key}: ${value},`; }); return `import { defineConfig } from "srcpack"; export default defineConfig({ - outDir: "${outDir}", + outDir: ${JSON.stringify(outDir)}, bundles: { ${bundleEntries.join("\n")} }, diff --git a/tests/e2e/cli.test.ts b/tests/e2e/cli.test.ts index 2cdc5b7..f75dca8 100644 --- a/tests/e2e/cli.test.ts +++ b/tests/e2e/cli.test.ts @@ -44,6 +44,21 @@ describe("cli", () => { ); }); + describe("version flag", () => { + test.each([["--version"], ["-v"]])( + "should print the package version when %p is passed", + async (flag) => { + const pkg = await Bun.file( + join(import.meta.dir, "../../package.json"), + ).json(); + const result = await runCli([flag]); + + expect(result.exitCode).toBe(0); + expect(result.stdout.trim()).toBe(pkg.version); + }, + ); + }); + describe("init subcommand", () => { test("should exit gracefully in non-TTY mode", async () => { const result = await runCli(["init"]); @@ -115,6 +130,14 @@ describe("cli", () => { expect(result.exitCode).toBe(1); expect(result.stderr).toContain("Unknown bundle: unknown"); }); + + test("should treat a subcommand name as a bundle when not first", async () => { + // `--since init` must diff against the `init` branch, not run the wizard + const result = await runCli(["--dry-run", "init"], { cwd: FIXTURE_PATH }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("Unknown bundle: init"); + }); }); describe("absolute outDir with custom root", () => { @@ -148,4 +171,222 @@ describe("cli", () => { expect(await outFile.exists()).toBe(true); }); }); + + describe("own output", () => { + const project = join(tmpdir(), `srcpack-own-${Date.now()}`); + + afterEach(async () => { + await rm(project, { recursive: true, force: true }); + }); + + test("should refuse to empty an outDir that holds the project root", async () => { + await mkdir(join(project, "src"), { recursive: true }); + await writeFile(join(project, "src/index.ts"), "export const x = 1;\n"); + await writeFile(join(project, "keep.md"), "# keep\n"); + await writeFile( + join(project, "srcpack.config.ts"), + `export default { outDir: ".", bundles: { app: "src/**/*" } };`, + ); + + const result = await runCli([], { cwd: project }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("contains the project root"); + // The whole project would otherwise be deleted + expect(await Bun.file(join(project, "keep.md")).exists()).toBe(true); + expect(await Bun.file(join(project, "src/index.ts")).exists()).toBe(true); + }); + + test("should keep other bundles when building a named subset", async () => { + await mkdir(join(project, "src"), { recursive: true }); + await writeFile(join(project, "src/index.ts"), "export const x = 1;\n"); + await writeFile( + join(project, "srcpack.config.ts"), + `export default { bundles: { web: "src/**/*", api: "src/**/*" } };`, + ); + + await runCli([], { cwd: project }); + // Emptying outDir would delete api.txt, which this run cannot rebuild + await runCli(["web"], { cwd: project }); + + expect(await Bun.file(join(project, ".srcpack/api.txt")).exists()).toBe( + true, + ); + expect(await Bun.file(join(project, ".srcpack/web.txt")).exists()).toBe( + true, + ); + }); + + test("should not bundle a previous run's output", async () => { + await mkdir(join(project, "src"), { recursive: true }); + await writeFile(join(project, "src/index.ts"), "export const x = 1;\n"); + await writeFile( + join(project, "srcpack.config.ts"), + `export default { emptyOutDir: false, bundles: { app: "**/*" } };`, + ); + + await runCli([], { cwd: project }); + const first = await Bun.file(join(project, ".srcpack/app.txt")).text(); + await runCli([], { cwd: project }); + const second = await Bun.file(join(project, ".srcpack/app.txt")).text(); + + // Without the guard each run nests the previous bundle one level deeper + expect(second).toBe(first); + expect(second).not.toContain(".srcpack/app.txt"); + }); + }); + + describe("ad-hoc git bundles", () => { + const repo = join(tmpdir(), `srcpack-adhoc-${Date.now()}`); + + async function git(...args: string[]) { + const proc = Bun.spawn( + [ + "git", + "-c", + "user.name=test", + "-c", + "user.email=test@example.com", + "-c", + "commit.gpgsign=false", + ...args, + ], + { cwd: repo, stdout: "pipe", stderr: "pipe" }, + ); + // Fail loudly: a silent setup failure would make the assertions lie + if ((await proc.exited) !== 0) { + throw new Error( + `git ${args.join(" ")} failed: ${await new Response(proc.stderr).text()}`, + ); + } + } + + afterEach(async () => { + await rm(repo, { recursive: true, force: true }); + }); + + test("should bundle staged files without a config file", async () => { + await mkdir(join(repo, "src"), { recursive: true }); + await writeFile(join(repo, "src/index.ts"), "export const x = 1;\n"); + await writeFile(join(repo, "src/other.ts"), "export const y = 2;\n"); + await git("init", "-b", "main"); + await git("add", "src/index.ts"); + + const result = await runCli(["--staged"], { cwd: repo }); + + expect(result.exitCode).toBe(0); + const bundle = Bun.file(join(repo, ".srcpack/staged.txt")); + expect(await bundle.exists()).toBe(true); + const content = await bundle.text(); + expect(content).toContain("src/index.ts"); + expect(content).not.toContain("src/other.ts"); + }); + + test("should bundle staged, unstaged, and untracked with --dirty", async () => { + await mkdir(join(repo, "src"), { recursive: true }); + await writeFile(join(repo, "src/committed.ts"), "export const a = 1;\n"); + await writeFile(join(repo, "src/tracked.ts"), "export const b = 2;\n"); + await git("init", "-b", "main"); + await git("add", "."); + await git("commit", "-m", "init"); + + await writeFile(join(repo, "src/tracked.ts"), "export const b = 22;\n"); + await writeFile(join(repo, "src/fresh.ts"), "export const c = 3;\n"); + await git("add", "src/tracked.ts"); + await writeFile(join(repo, "src/tracked.ts"), "export const b = 222;\n"); + + const result = await runCli(["--dirty"], { cwd: repo }); + + expect(result.exitCode).toBe(0); + const content = await Bun.file(join(repo, ".srcpack/dirty.txt")).text(); + expect(content).toContain("src/tracked.ts"); // staged + unstaged + expect(content).toContain("src/fresh.ts"); // untracked + expect(content).not.toContain("src/committed.ts"); // unchanged + }); + + test("should bundle branch work with --since, including untracked", async () => { + await mkdir(join(repo, "src"), { recursive: true }); + await writeFile(join(repo, "src/base.ts"), "export const a = 1;\n"); + await git("init", "-b", "main"); + await git("add", "."); + await git("commit", "-m", "init"); + + await git("checkout", "-b", "feature"); + await writeFile(join(repo, "src/onbranch.ts"), "export const b = 2;\n"); + await git("add", "src/onbranch.ts"); + await git("commit", "-m", "branch work"); + await writeFile(join(repo, "src/untracked.ts"), "export const c = 3;\n"); + + const result = await runCli(["--since", "main"], { cwd: repo }); + + expect(result.exitCode).toBe(0); + const content = await Bun.file(join(repo, ".srcpack/since.txt")).text(); + expect(content).toContain("src/onbranch.ts"); + expect(content).toContain("src/untracked.ts"); + expect(content).not.toContain("src/base.ts"); + }); + + test("should skip writing when nothing is staged", async () => { + await mkdir(repo, { recursive: true }); + await writeFile(join(repo, "README.md"), "# test\n"); + await git("init", "-b", "main"); + + const result = await runCli(["--staged"], { cwd: repo }); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("skipped"); + expect(await Bun.file(join(repo, ".srcpack/staged.txt")).exists()).toBe( + false, + ); + }); + + test("should report a git failure without a stack trace", async () => { + await mkdir(repo, { recursive: true }); + + const result = await runCli(["--staged"], { cwd: repo }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("Not a git repository"); + expect(result.stderr).not.toContain("at "); + }); + + test("should reject combining an ad-hoc flag with named bundles", async () => { + const result = await runCli(["code", "--staged"], { cwd: FIXTURE_PATH }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("Cannot combine --staged"); + }); + + test("should require a revision for --since", async () => { + const result = await runCli(["--since"], { cwd: FIXTURE_PATH }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("Missing revision"); + }); + + test("should not bundle a previous ad-hoc run's output", async () => { + // No config, so outDir is the only thing marking srcpack's own output — + // and `git:untracked` reports `.srcpack/dirty.txt` unless it is excluded + await mkdir(join(repo, "src"), { recursive: true }); + await writeFile(join(repo, "src/index.ts"), "export const x = 1;\n"); + await git("init", "-b", "main"); + + await runCli(["--dirty"], { cwd: repo }); + const first = await Bun.file(join(repo, ".srcpack/dirty.txt")).text(); + await runCli(["--dirty"], { cwd: repo }); + const second = await Bun.file(join(repo, ".srcpack/dirty.txt")).text(); + + expect(second).toBe(first); + expect(second).not.toContain(".srcpack/dirty.txt"); + }); + + test("should reject a range for --since", async () => { + const result = await runCli(["--since", "main...HEAD"], { + cwd: FIXTURE_PATH, + }); + + expect(result.exitCode).toBe(1); + expect(result.stderr).toContain("not a range"); + }); + }); }); diff --git a/tests/unit/bundle.test.ts b/tests/unit/bundle.test.ts index 8829da9..1c28c3c 100644 --- a/tests/unit/bundle.test.ts +++ b/tests/unit/bundle.test.ts @@ -201,6 +201,64 @@ describe("resolvePatterns", () => { expect(files).toContain("./../gitignore-project/src/index.ts"); }); + + test("should resolve absolute patterns", async () => { + // fast-glob returns absolute paths for absolute patterns, so they must not + // be joined onto cwd + const files = await resolvePatterns( + join(gitignoreFixturesDir, "src/**/*.ts"), + fixturesDir, + ); + + expect(files).toContain(join(gitignoreFixturesDir, "src/index.ts")); + }); + + test("should bundle content from an absolute pattern", async () => { + const files = await resolvePatterns( + join(gitignoreFixturesDir, "src/index.ts"), + fixturesDir, + ); + const result = await createBundle(files, fixturesDir); + + expect(result.index).toHaveLength(1); + expect(result.index[0]!.lines).toBeGreaterThan(0); + }); + + test("should bundle a file once when named both ways", async () => { + const files = await resolvePatterns( + ["src/index.ts", join(fixturesDir, "src/index.ts")], + fixturesDir, + ); + + expect(files).toEqual(["src/index.ts"]); + }); + + test("should skip files under an output directory", async () => { + const files = await resolvePatterns("src/**/*", fixturesDir, [ + join(fixturesDir, "src/utils"), + ]); + + expect(files).toContain("src/index.ts"); + expect(files.some((f) => f.startsWith("src/utils/"))).toBe(false); + }); + + test("should skip an output file without skipping its siblings", async () => { + const files = await resolvePatterns("src/**/*", fixturesDir, [ + join(fixturesDir, "src/index.ts"), + ]); + + expect(files).not.toContain("src/index.ts"); + expect(files.length).toBeGreaterThan(0); + }); + + test("should not skip paths that merely share a prefix with an output", async () => { + // "src/util" is a prefix of "src/utils" but not a parent of it + const files = await resolvePatterns("src/**/*", fixturesDir, [ + join(fixturesDir, "src/util"), + ]); + + expect(files).toContain("src/utils/helpers.ts"); + }); }); describe("formatIndex", () => { @@ -405,14 +463,13 @@ describe("createBundle", () => { describe("bundleOne", () => { test("should include index by default", async () => { - const result = await bundleOne("web", "src/index.ts", fixturesDir); + const result = await bundleOne("src/index.ts", fixturesDir); expect(result.content).toContain("# Index"); }); test("should include index when explicitly enabled", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", index: true }, fixturesDir, ); @@ -422,7 +479,6 @@ describe("bundleOne", () => { test("should omit index when disabled in config", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", index: false }, fixturesDir, ); @@ -432,14 +488,13 @@ describe("bundleOne", () => { }); test("should include index for string pattern config", async () => { - const result = await bundleOne("web", "src/index.ts", fixturesDir); + const result = await bundleOne("src/index.ts", fixturesDir); expect(result.content).toContain("# Index"); }); test("should include index for array pattern config", async () => { const result = await bundleOne( - "web", ["src/index.ts", "!src/utils/**"], fixturesDir, ); @@ -449,7 +504,6 @@ describe("bundleOne", () => { test("should prepend prompt from config", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", prompt: "Review this code." }, fixturesDir, ); @@ -461,7 +515,6 @@ describe("bundleOne", () => { test("should ignore empty prompt in config", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", prompt: "" }, fixturesDir, ); @@ -472,7 +525,6 @@ describe("bundleOne", () => { test("should ignore undefined prompt in config", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", prompt: undefined }, fixturesDir, ); @@ -483,7 +535,6 @@ describe("bundleOne", () => { test("should load prompt from file when path starts with ./", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", prompt: "./prompts/review.md" }, fixturesDir, ); @@ -497,7 +548,6 @@ describe("bundleOne", () => { // Verify ~/ paths are treated as file paths (throws for non-existent file) await expect( bundleOne( - "web", { include: "src/index.ts", prompt: "~/non-existent-srcpack-test.md" }, fixturesDir, ), @@ -506,7 +556,6 @@ describe("bundleOne", () => { test("should use literal prompt when not a path", async () => { const result = await bundleOne( - "web", { include: "src/index.ts", prompt: "Check for bugs." }, fixturesDir, ); diff --git a/tests/unit/config-discovery.test.ts b/tests/unit/config-discovery.test.ts new file mode 100644 index 0000000..43c4452 --- /dev/null +++ b/tests/unit/config-discovery.test.ts @@ -0,0 +1,45 @@ +import { mkdtemp, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, describe, expect, test } from "bun:test"; +import { loadConfig } from "../../src/config.ts"; + +let dir: string; + +afterEach(async () => { + if (dir) await rm(dir, { recursive: true, force: true }); +}); + +/** + * `srcpack init` writes `srcpack.config.mts` in a CommonJS project, so it has + * to be discoverable — cosmiconfig only looks at the names in `searchPlaces`. + */ +describe("config discovery", () => { + test("should find srcpack.config.mts", async () => { + dir = await mkdtemp(join(tmpdir(), "srcpack-cfg-")); + await writeFile( + join(dir, "srcpack.config.mts"), + `export default { bundles: { app: "src/**/*" } };\n`, + ); + + const config = await loadConfig(dir); + + expect(config?.bundles).toEqual({ app: "src/**/*" }); + }); + + test("should prefer srcpack.config.ts when both exist", async () => { + dir = await mkdtemp(join(tmpdir(), "srcpack-cfg-")); + await writeFile( + join(dir, "srcpack.config.ts"), + `export default { bundles: { fromTs: "src/**/*" } };\n`, + ); + await writeFile( + join(dir, "srcpack.config.mts"), + `export default { bundles: { fromMts: "src/**/*" } };\n`, + ); + + const config = await loadConfig(dir); + + expect(config?.bundles).toHaveProperty("fromTs"); + }); +}); diff --git a/tests/unit/gdrive.test.ts b/tests/unit/gdrive.test.ts new file mode 100644 index 0000000..12cfc9e --- /dev/null +++ b/tests/unit/gdrive.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, test } from "bun:test"; +import { escapeQueryValue } from "../../src/gdrive.ts"; + +/** + * `findFile` interpolates a file name into a single-quoted Drive query and + * the caller overwrites whatever it returns, so a quote that escapes the + * literal picks a different file to destroy. + */ +describe("escapeQueryValue", () => { + test("should leave ordinary names untouched", () => { + expect(escapeQueryValue("web.txt")).toBe("web.txt"); + }); + + test("should escape a quote so it cannot close the literal", () => { + expect(escapeQueryValue("it's.txt")).toBe("it\\'s.txt"); + }); + + test("should escape backslashes before quotes", () => { + // Escaping the quote first would leave `\\'` — an escaped backslash + // followed by a live quote + expect(escapeQueryValue("a\\'b")).toBe("a\\\\\\'b"); + }); + + test("should neutralize a name that rewrites the query", () => { + const name = "x' or name = 'secret.doc"; + const query = `name = '${escapeQueryValue(name)}' and 'root' in parents`; + + // The whole name stays one literal: no bare `'` remains to split it + expect(query).toBe( + "name = 'x\\' or name = \\'secret.doc' and 'root' in parents", + ); + }); +}); diff --git a/tests/unit/git.test.ts b/tests/unit/git.test.ts new file mode 100644 index 0000000..34ba578 --- /dev/null +++ b/tests/unit/git.test.ts @@ -0,0 +1,319 @@ +import { execFile } from "node:child_process"; +import { mkdtemp, mkdir, rm, symlink, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { promisify } from "node:util"; +import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import { createBundle, resolvePatterns } from "../../src/bundle.ts"; +import { ConfigError } from "../../src/config.ts"; +import { GitError, isGitSource, resolveGitSource } from "../../src/git.ts"; + +const execFileAsync = promisify(execFile); + +let repo: string; +let outside: string; + +/** Run git with identity flags so the test doesn't depend on global config. */ +function git(...args: string[]) { + return execFileAsync( + "git", + [ + "-c", + "user.name=test", + "-c", + "user.email=test@example.com", + "-c", + "commit.gpgsign=false", + ...args, + ], + { cwd: repo }, + ); +} + +/** Content defaults to something unique — identical files trip git's rename + * detection, which would turn a delete + add pair into a single R entry. */ +function write(path: string, content = `// ${path}\n`) { + return writeFile(join(repo, path), content); +} + +/** + * Build a repo covering every state a bundle has to handle: + * committed, staged, unstaged, untracked, deleted, ignored, binary, + * and a diverged branch for `git:`. + */ +beforeAll(async () => { + repo = await mkdtemp(join(tmpdir(), "srcpack-git-")); + + await git("init", "-b", "main"); + await write(".gitignore", "ignored/\n*.log\n"); + await write("base.ts"); + await write("mod.ts"); + await write("gone.ts"); + await write("kept.ts"); + await mkdir(join(repo, "pkg/src"), { recursive: true }); + await write("pkg/src/deep.ts"); + await git("add", "."); + await git("commit", "-m", "init"); + + // Diverge: main gains a file and edits another. Neither is this branch's + // work, so a merge-base comparison must report neither. (The added file + // alone wouldn't prove it — it reads as a deletion, which ACMR filters.) + await git("checkout", "-b", "feature"); + await git("checkout", "main"); + await write("theirs.ts"); + await write("kept.ts", "edited on main\n"); + await git("add", "theirs.ts", "kept.ts"); + await git("commit", "-m", "their work"); + await git("checkout", "feature"); + + await write("committed-on-branch.ts"); + await git("add", "committed-on-branch.ts"); + await git("commit", "-m", "my work"); + + await write("base.ts", "staged change\n"); + await write("pkg/src/deep.ts", "staged deep change\n"); + await git("add", "base.ts", "pkg/src/deep.ts"); + + await write("mod.ts", "unstaged change\n"); + + await write("new.ts"); + await write("notes.md"); // untracked non-.ts, so exclusion tests can't pass vacuously + await write("pkg/src/fresh.ts"); // untracked inside a subdirectory + + await git("rm", "-q", "gone.ts"); + + // Staged, then removed from the worktree before bundling + await write("ghost.ts"); + await git("add", "ghost.ts"); + await rm(join(repo, "ghost.ts")); + + // Binary content is excluded regardless of git state + await writeFile(join(repo, "bin.dat"), Buffer.from([0x41, 0x00, 0x42])); + await git("add", "bin.dat"); + + // A tracked symlink escaping the repo must not leak the target's contents + outside = await mkdtemp(join(tmpdir(), "srcpack-outside-")); + await writeFile(join(outside, "secret.txt"), "SECRET\n"); + await symlink(join(outside, "secret.txt"), join(repo, "leak.txt")); + await git("add", "leak.txt"); + + await mkdir(join(repo, "ignored"), { recursive: true }); + await write("ignored/secret.ts"); + await write("debug.log"); +}); + +afterAll(async () => { + await rm(outside, { recursive: true, force: true }); + await rm(repo, { recursive: true, force: true }); +}); + +describe("isGitSource", () => { + test("should detect the git: prefix", () => { + expect(isGitSource("git:staged")).toBe(true); + expect(isGitSource("src/**/*.ts")).toBe(false); + }); +}); + +describe("resolveGitSource", () => { + test("should list staged files", async () => { + const files = await resolveGitSource("git:staged", repo); + + expect(files).toContain("base.ts"); + expect(files).not.toContain("mod.ts"); + expect(files).not.toContain("new.ts"); + }); + + test("should omit staged deletions", async () => { + const files = await resolveGitSource("git:staged", repo); + + expect(files).not.toContain("gone.ts"); + }); + + test("should list unstaged files only", async () => { + const files = await resolveGitSource("git:unstaged", repo); + + expect(files).toContain("mod.ts"); + expect(files).not.toContain("base.ts"); + expect(files).not.toContain("new.ts"); + }); + + test("should list untracked files, respecting .gitignore", async () => { + const files = await resolveGitSource("git:untracked", repo); + + expect(files).toContain("new.ts"); + expect(files).not.toContain("ignored/secret.ts"); + expect(files).not.toContain("debug.log"); + }); + + test("should union all three for dirty", async () => { + const files = await resolveGitSource("git:dirty", repo); + + expect(files).toContain("base.ts"); + expect(files).toContain("mod.ts"); + expect(files).toContain("new.ts"); + expect(files).not.toContain("kept.ts"); + }); + + test("should not duplicate a file staged and modified again", async () => { + await write("base.ts", "staged, then modified again\n"); + let files: string[]; + try { + files = await resolveGitSource("git:dirty", repo); + } finally { + // Restore even on failure — later tests share this repo + await write("base.ts", "staged change\n"); + } + + expect(files.filter((f) => f === "base.ts")).toHaveLength(1); + }); + + test("should compare a revision against the merge base", async () => { + const files = await resolveGitSource("git:main", repo); + + expect(files).toContain("committed-on-branch.ts"); + expect(files).toContain("base.ts"); // uncommitted work counts + // Changed on main after the branch point, so not this branch's work. + // Without --merge-base, kept.ts would show as modified. + expect(files).not.toContain("kept.ts"); + expect(files).not.toContain("theirs.ts"); + }); + + test("should scope results to a subdirectory", async () => { + // Matches a monorepo config whose `root` is one package + const files = await resolveGitSource("git:staged", join(repo, "pkg")); + + expect(files).toContain("src/deep.ts"); // relative to the subdirectory + expect(files).not.toContain("base.ts"); // outside it + expect(files).not.toContain("pkg/src/deep.ts"); + }); + + test("should scope untracked files to a subdirectory", async () => { + const files = await resolveGitSource("git:untracked", join(repo, "pkg")); + + expect(files).toContain("src/fresh.ts"); + expect(files).not.toContain("pkg/src/fresh.ts"); + expect(files).not.toContain("new.ts"); + }); + + test("should pass ranges through to git", async () => { + const files = await resolveGitSource("git:HEAD~1..HEAD", repo); + + expect(files).toEqual(["committed-on-branch.ts"]); + }); + + test("should reject an empty source", async () => { + await expect(resolveGitSource("git:", repo)).rejects.toThrow( + /Empty git source/, + ); + }); + + test("should reject a revision that git would read as a flag", async () => { + await expect(resolveGitSource("git:--exit-code", repo)).rejects.toThrow( + /starts with "-"/, + ); + }); + + test("should report an unknown revision", async () => { + // git's own wording, not a generic failure + await expect(resolveGitSource("git:no-such-ref", repo)).rejects.toThrow( + /no-such-ref/, + ); + }); + + test("should report a directory that is not a repository", async () => { + const plain = await mkdtemp(join(tmpdir(), "srcpack-plain-")); + try { + // git diff falls back to --no-index here and prints usage, so the + // message must come from the repository check instead + await expect(resolveGitSource("git:staged", plain)).rejects.toThrow( + /Not a git repository/, + ); + } finally { + await rm(plain, { recursive: true, force: true }); + } + }); + + test("should surface a GitError type for callers", async () => { + await expect(resolveGitSource("git:", repo)).rejects.toBeInstanceOf( + GitError, + ); + }); +}); + +describe("resolvePatterns with git sources", () => { + test("should resolve a git source to files", async () => { + const files = await resolvePatterns("git:staged", repo); + + expect(files).toContain("base.ts"); + }); + + test("should skip files git listed but the worktree no longer has", async () => { + const files = await resolvePatterns("git:staged", repo); + + expect(files).toContain("base.ts"); // guards against a vacuous pass + expect(files).not.toContain("ghost.ts"); + }); + + test("should skip binary files", async () => { + const files = await resolvePatterns("git:staged", repo); + + expect(files).toContain("base.ts"); + expect(files).not.toContain("bin.dat"); + }); + + test("should not follow a symlink out of the repository", async () => { + const files = await resolvePatterns("git:staged", repo); + const bundle = await createBundle(files, repo); + + expect(files).toContain("base.ts"); + expect(files).not.toContain("leak.txt"); + expect(bundle.content).not.toContain("SECRET"); + }); + + test("should apply ! exclusions to git sources", async () => { + const files = await resolvePatterns(["git:dirty", "!*.ts"], repo); + + expect(files).toContain("notes.md"); + expect(files).not.toContain("base.ts"); + expect(files).not.toContain("new.ts"); + }); + + test("should combine git sources with globs", async () => { + const files = await resolvePatterns(["git:staged", "kept.ts"], repo); + + expect(files).toContain("base.ts"); + expect(files).toContain("kept.ts"); + }); + + test("should ignore .gitignore for git sources", async () => { + // Tracked despite matching .gitignore — git reports it, so it belongs + await git("add", "-f", "debug.log"); + let files: string[]; + try { + files = await resolvePatterns("git:staged", repo); + } finally { + await git("rm", "-q", "--cached", "debug.log"); + } + + expect(files).toContain("debug.log"); + }); + + test("should sort and deduplicate across overlapping sources", async () => { + const files = await resolvePatterns(["git:staged", "git:dirty"], repo); + + expect(files.length).toBeGreaterThan(1); + expect(files).toEqual([...new Set(files)].sort()); + }); + + test("should reject a git source with the ! prefix", async () => { + await expect( + resolvePatterns(["src/**", "!git:staged"], repo), + ).rejects.toThrow(ConfigError); + }); + + test("should reject a git source with the + prefix", async () => { + await expect(resolvePatterns(["+git:staged"], repo)).rejects.toThrow( + ConfigError, + ); + }); +}); diff --git a/tests/unit/init.test.ts b/tests/unit/init.test.ts new file mode 100644 index 0000000..395a949 --- /dev/null +++ b/tests/unit/init.test.ts @@ -0,0 +1,77 @@ +import { describe, expect, test } from "bun:test"; +import { configFileName, generateConfig } from "../../src/init.ts"; + +/** + * Node picks a `.ts` file's module format from the nearest package.json, so + * the generated config — which opens with `import { defineConfig }` — is a + * syntax error in a CommonJS project. `.mts` is ESM either way. + */ +describe("configFileName", () => { + test("should use .ts in an ESM project", () => { + expect(configFileName("module")).toBe("srcpack.config.ts"); + }); + + test("should use .mts in a CommonJS project", () => { + expect(configFileName("commonjs")).toBe("srcpack.config.mts"); + }); + + test("should use .mts when type is absent", () => { + // `npm init -y` writes no `type` field at all + expect(configFileName(undefined)).toBe("srcpack.config.mts"); + }); +}); + +/** + * The generated file is TypeScript that srcpack itself loads on the next run, + * so a value that breaks the syntax — or silently changes meaning — is a bug + * the user only discovers later. + */ +describe("generateConfig", () => { + test("should generate a config for a single pattern", () => { + const config = generateConfig( + [{ name: "app", include: ["src/**/*"] }], + ".srcpack", + ); + + expect(config).toContain(`outDir: ".srcpack"`); + expect(config).toContain(`app: "src/**/*",`); + }); + + test("should generate an array for multiple patterns", () => { + const config = generateConfig( + [{ name: "app", include: ["src/**/*", "!bun.lock"] }], + ".srcpack", + ); + + expect(config).toContain(`app: ["src/**/*","!bun.lock"],`); + }); + + test("should quote a hyphenated bundle name", () => { + // `my-app: "..."` is not valid TypeScript, but init accepts hyphens + const config = generateConfig( + [{ name: "my-app", include: ["src/**/*"] }], + ".srcpack", + ); + + expect(config).toContain(`"my-app": "src/**/*",`); + }); + + test("should escape backslashes in patterns", () => { + // Unescaped, `"src\\**\\*"` parses back as `src***` + const config = generateConfig( + [{ name: "app", include: ["src\\**\\*"] }], + ".srcpack", + ); + + expect(config).toContain(String.raw`app: "src\\**\\*",`); + }); + + test("should escape quotes in outDir", () => { + const config = generateConfig( + [{ name: "app", include: ["src/**/*"] }], + `out"dir`, + ); + + expect(config).toContain(String.raw`outDir: "out\"dir"`); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 6609671..532b36f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,10 @@ "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, + // TypeScript 6 defaults `types` to [] instead of auto-enumerating @types/*. + // @types/bun supplies the Bun globals and re-exports Node's, covering both. + "types": ["bun"], + // Emit declarations only (Bun handles JS bundling) "declaration": true, "emitDeclarationOnly": true,