From 867260d713e0c082ea59822c1d7218f7c007bc7d Mon Sep 17 00:00:00 2001 From: Konstantin Tarkus Date: Sat, 15 Aug 2026 11:08:03 +0200 Subject: [PATCH 1/2] feat: bundle git change sets with `git:` source tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pattern may now name a set of changed files instead of a glob: `git:staged`, `git:unstaged`, `git:untracked`, `git:dirty`, or `git:`. CLI flags `--staged`, `--dirty` and `--since ` build the same bundle ad hoc, with no config file at all. Globs cannot express "what I'm currently changing", which is the most common reason to hand code to an LLM. Resolving the set lazily inside the pattern array keeps the config plain data — it still works in package.json, composes with `!` exclusions, and concrete paths never get re-matched as globs (a staged `src/[id].tsx` would silently match nothing). See ADR 001. Also raises the Node floor to ^22.18 so cosmiconfig 10 can load `srcpack.config.ts` via Node's built-in type stripping instead of a bundled TypeScript parser, cutting the published CLI from 10.8 MB to 2.4 MB. See ADR 002. Fixes found while reviewing the above: - `outDir: "."` deleted the entire project, then reported success - reruns bundled their own output, nesting it deeper each time - `srcpack web` emptied outDir, destroying bundles it could not rebuild - symlinks were followed, so a tracked link could pull in a file from outside the project and upload it - a quote in a bundle filename could make the Drive query resolve to an unrelated file, which the upload then overwrote - OAuth refresh tokens were written world-readable (0644) - `srcpack init` generated invalid TypeScript for hyphenated bundle names, and dropped backslashes from patterns - failed uploads exited 0 - `--since init` ran the init wizard instead of diffing against `init` Docs now deploy from GitHub Actions rather than the gh-pages branch. --- .github/workflows/ci.yml | 3 +- .github/workflows/docs.yml | 45 +++ .github/workflows/release.yml | 5 +- .vitepress/config.ts | 15 +- README.md | 16 +- bun.lock | 495 +++++++++------------------ docs/adr/001-git-source-tokens.md | 88 +++++ docs/adr/002-minimum-node-version.md | 46 +++ docs/adr/index.md | 13 + docs/cli.md | 36 +- docs/configuration.md | 68 +++- docs/getting-started.md | 24 +- docs/index.md | 5 +- docs/upload.md | 4 +- package.json | 38 +- src/bundle.ts | 170 ++++++--- src/cli.ts | 223 +++++++++--- src/config.ts | 9 + src/gdrive.ts | 80 +++-- src/git.ts | 131 +++++++ src/init.ts | 20 +- tests/e2e/cli.test.ts | 241 +++++++++++++ tests/unit/bundle.test.ts | 71 +++- tests/unit/gdrive.test.ts | 33 ++ tests/unit/git.test.ts | 319 +++++++++++++++++ tests/unit/init.test.ts | 57 +++ tsconfig.json | 4 + 27 files changed, 1725 insertions(+), 534 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/adr/001-git-source-tokens.md create mode 100644 docs/adr/002-minimum-node-version.md create mode 100644 docs/adr/index.md create mode 100644 src/git.ts create mode 100644 tests/unit/gdrive.test.ts create mode 100644 tests/unit/git.test.ts create mode 100644 tests/unit/init.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6ac830..f549d31 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 with: bun-version: latest @@ -20,3 +20,4 @@ jobs: - run: bun prettier --check . - run: bun test tests/unit/ tests/e2e/ - run: bun run build + - run: bun run docs:build 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..b781ab8 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 @@ -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..dd04c1c --- /dev/null +++ b/docs/adr/002-minimum-node-version.md @@ -0,0 +1,46 @@ +# 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. + +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..d698c91 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 diff --git a/docs/configuration.md b/docs/configuration.md index 00ff00c..4abba77 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -61,6 +61,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 +123,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 +138,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` — 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. -- Files matching `.gitignore` patterns -- Binary files (images, fonts, compiled assets) -- `node_modules/` -- `.git/` -- Lock files (`package-lock.json`, `yarn.lock`, etc.) +Everything else matched by a pattern is included, so exclude what you don't +want explicitly: `["src/**/*", "!bun.lock"]`. ## Examples @@ -211,9 +263,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..a2ff90b 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), 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..b0fd5e7 100644 --- a/src/init.ts +++ b/src/init.ts @@ -86,7 +86,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 +102,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 +116,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/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..79713f4 --- /dev/null +++ b/tests/unit/init.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, test } from "bun:test"; +import { generateConfig } from "../../src/init.ts"; + +/** + * 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, From 0289dbffc1ef94752219ea95d417973f6d491ad2 Mon Sep 17 00:00:00 2001 From: Konstantin Tarkus Date: Sat, 15 Aug 2026 11:29:27 +0200 Subject: [PATCH 2/2] fix: load srcpack.config in CommonJS projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Node derives a `.ts` file's module format from the nearest package.json `type`, so in a CommonJS project — the `npm init` default — the generated config's `import { defineConfig }` line is a syntax error. cosmiconfig 9 compiled the file with its bundled TypeScript and hid this; cosmiconfig 10 type-strips it, so 0.2.0 would have shipped broken for those projects. `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 since that is the name the docs use. The suite runs on Bun, which loads either extension regardless of package type and so cannot see this failure. CI now installs the packed tarball into a CommonJS project and runs the CLI under Node. --- .github/workflows/ci.yml | 20 +++++++++++++ README.md | 2 +- docs/adr/002-minimum-node-version.md | 12 ++++++++ docs/cli.md | 8 +++-- docs/configuration.md | 23 ++++++++++++-- src/config.ts | 3 +- src/init.ts | 29 ++++++++++++++---- tests/unit/config-discovery.test.ts | 45 ++++++++++++++++++++++++++++ tests/unit/init.test.ts | 22 +++++++++++++- 9 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 tests/unit/config-discovery.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f549d31..5ee256f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,9 +15,29 @@ jobs: - 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/README.md b/README.md index b781ab8..4f37ecd 100644 --- a/README.md +++ b/README.md @@ -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"; diff --git a/docs/adr/002-minimum-node-version.md b/docs/adr/002-minimum-node-version.md index dd04c1c..56f3f96 100644 --- a/docs/adr/002-minimum-node-version.md +++ b/docs/adr/002-minimum-node-version.md @@ -42,5 +42,17 @@ Config files must use erasable syntax only. Type annotations, `satisfies`, and 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/cli.md b/docs/cli.md index d698c91..c6b5c63 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -242,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 4abba77..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 diff --git a/src/config.ts b/src/config.ts index a2ff90b..e8a68b0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -139,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/init.ts b/src/init.ts index b0fd5e7..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( 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/init.test.ts b/tests/unit/init.test.ts index 79713f4..395a949 100644 --- a/tests/unit/init.test.ts +++ b/tests/unit/init.test.ts @@ -1,5 +1,25 @@ import { describe, expect, test } from "bun:test"; -import { generateConfig } from "../../src/init.ts"; +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,