From 0129adf9a86d55d02f18597516dd89a742820e5a Mon Sep 17 00:00:00 2001 From: Justin Merrell Date: Mon, 30 Mar 2026 17:00:58 +0000 Subject: [PATCH] feat!: remove deprecated APIs, rename MushError to MusherError, and upgrade toolchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove deprecated load(), getAsset(), and getAssetsByType() methods. Rename MushError → MusherError for consistency with the SDK naming. Add BundleAssetNotFoundError for typed asset lookup failures. Simplify cache write to return void instead of CachedBundle. Upgrade Biome 2.0, TypeScript 5.9, Vitest 3.2, and pnpm 10.33. Add basic usage examples and vitest coverage config. BREAKING CHANGE: MushError renamed to MusherError. Deprecated methods MusherClient.load(), Bundle.getAsset(), and Bundle.getAssetsByType() have been removed. Cache.write() no longer returns CachedBundle. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/ci.yml | 2 +- README.md | 52 +- Taskfile.yml | 9 + biome.json | 31 +- examples/README.md | 57 +- examples/basics/cache-management.ts | 53 ++ examples/basics/configure-client.ts | 50 ++ examples/basics/explore-all-assets.ts | 49 ++ examples/basics/select-and-materialize.ts | 55 ++ examples/package.json | 2 +- package.json | 6 +- packages/musher/README.md | 141 ++++- packages/musher/package.json | 19 +- packages/musher/src/bundle.ts | 41 +- packages/musher/src/cache.ts | 32 +- packages/musher/src/client.ts | 42 -- packages/musher/src/config.ts | 4 +- packages/musher/src/errors.ts | 27 +- packages/musher/src/http.ts | 1 + packages/musher/src/index.ts | 50 +- packages/musher/src/ref.ts | 4 +- packages/musher/src/resources/bundles.ts | 2 +- packages/musher/src/schemas/index.ts | 6 +- packages/musher/src/types.ts | 32 -- packages/musher/tests/bundle.test.ts | 21 +- packages/musher/tests/cache.test.ts | 28 +- packages/musher/tests/client.test.ts | 13 +- packages/musher/tests/ref.test.ts | 10 +- packages/musher/vitest.config.ts | 11 + pnpm-lock.yaml | 629 +++++++++++++++++----- tsconfig.base.json | 4 +- 31 files changed, 1066 insertions(+), 417 deletions(-) create mode 100644 examples/basics/cache-management.ts create mode 100644 examples/basics/configure-client.ts create mode 100644 examples/basics/explore-all-assets.ts create mode 100644 examples/basics/select-and-materialize.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73d3e63..9f75fd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20, 22] + node-version: [20, 22, 24] steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 diff --git a/README.md b/README.md index e77ecae..f0e1c16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # Musher TypeScript SDK -Official TypeScript SDK for the [Musher](https://musher.dev) platform. +[![npm](https://img.shields.io/npm/v/@musher-dev/musher-sdk)](https://www.npmjs.com/package/@musher-dev/musher-sdk) +[![CI](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) +![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen) + +Official TypeScript SDK for the [Musher](https://musher.dev) platform. Pull, cache, and load bundled AI agent assets — skills, prompts, toolsets, and agent specs — with typed handles, content-addressable caching, and platform adapters for Claude Code, OpenAI Agents, and VS Code. ## Packages @@ -32,6 +37,8 @@ const file = bundle.file("prompts/system.md"); console.log(file?.text()); ``` +## More Capabilities + Resolve metadata without downloading: ```typescript @@ -41,7 +48,7 @@ const meta = await resolve("acme/code-review-kit:1.2.0"); console.log(meta.version); ``` -Use `MusherClient` directly when you need custom configuration: +Custom client configuration: ```typescript import { MusherClient } from "@musher-dev/musher-sdk"; @@ -54,7 +61,46 @@ const client = new MusherClient({ const bundle = await client.pull("acme/code-review-kit:1.2.0"); ``` -See [`examples/`](./examples/) for more complete runnable examples including Claude, OpenAI, and VS Code integrations. +Cache management: + +```typescript +const stats = await client.cache.stats(); +console.log(stats.entryCount, stats.blobSizeBytes); +await client.cache.clean(); +``` + +Filter and materialize a subset: + +```typescript +const selection = bundle.select({ skills: ["lint-rules"], prompts: ["system"] }); +await selection.materialize("./output"); +``` + +Error handling: + +```typescript +import { pull, NotFoundError, MusherError } from "@musher-dev/musher-sdk"; + +try { + await pull("acme/missing:1.0.0"); +} catch (err) { + if (err instanceof NotFoundError) console.error(err.problem.detail); +} +``` + +## Authentication + +Set `MUSHER_API_KEY` in your environment, or see the [package docs](./packages/musher/README.md#authentication) for all credential resolution options. + +## Platform Adapters + +Install bundles directly into your AI toolchain: + +- **Claude Code** — `installClaudeSkills()`, `exportClaudePlugin()` ([examples](./examples/claude/)) +- **OpenAI Agents** — `exportOpenAILocalSkill()`, `exportOpenAIInlineSkill()` ([examples](./examples/openai/)) +- **VS Code** — `installVSCodeSkills()` ([examples](./examples/ide/)) + +See [`examples/`](./examples/) for 15 runnable examples covering basic operations and platform integrations. ## Development diff --git a/Taskfile.yml b/Taskfile.yml index bf882db..6a9b910 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -56,6 +56,15 @@ tasks: cmds: - pnpm -r check:attw + ci: + desc: Run full CI pipeline (check + build + publish validation) + cmds: + - task: check + - task: check:exports + - task: build + - pnpm -r check:publint + - pnpm -r check:attw + clean: desc: Clean build artifacts cmds: diff --git a/biome.json b/biome.json index 630e096..fdc152d 100644 --- a/biome.json +++ b/biome.json @@ -1,8 +1,6 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "organizeImports": { - "enabled": true - }, + "$schema": "https://biomejs.dev/schemas/2.4.10/schema.json", + "assist": { "actions": { "source": { "organizeImports": "on" } } }, "formatter": { "enabled": true, "indentStyle": "tab", @@ -11,16 +9,23 @@ "linter": { "enabled": true, "rules": { - "all": true, + "recommended": true, + "complexity": { + "noExcessiveCognitiveComplexity": "warn", + "useLiteralKeys": "off" + }, "correctness": { "noNodejsModules": "off", "noUndeclaredDependencies": "off", "noUnusedImports": "error", "noUnusedVariables": "error" }, + "performance": { + "noBarrelFile": "off", + "noNamespaceImport": "off" + }, "style": { "noDefaultExport": "off", - "noNamespaceImport": "off", "noNonNullAssertion": "error", "noParameterProperties": "off", "useConst": "error", @@ -32,27 +37,19 @@ "suspicious": { "noExplicitAny": "error", "useAwait": "off" - }, - "complexity": { - "noExcessiveCognitiveComplexity": "warn", - "useLiteralKeys": "off" - }, - "performance": { - "noBarrelFile": "off" } } }, "files": { - "ignore": ["**/dist/**", "**/node_modules/**", "**/.svelte-kit/**"] + "includes": ["**", "!**/dist", "!**/node_modules", "!**/.svelte-kit"] }, "overrides": [ { - "include": ["examples/**"], + "includes": ["**/examples/**"], "linter": { "rules": { "suspicious": { - "noConsole": "off", - "noConsoleLog": "off" + "noConsole": "off" } } } diff --git a/examples/README.md b/examples/README.md index f4a19de..d7a7e09 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,8 @@ # Musher SDK Examples -Runnable TypeScript examples for `@musher-dev/musher-sdk`. +Runnable TypeScript examples for [`@musher-dev/musher-sdk`](../packages/musher/). + +Examples are organized into four categories: **basics** (core SDK operations), **claude** (Claude Code integration), **openai** (OpenAI Agents integration), and **ide** (VS Code integration). ## Prerequisites @@ -20,19 +22,33 @@ npx tsx examples/basics/pull-bundle.ts ## Examples -| File | Status | Description | -|------|--------|-------------| -| `basics/pull-bundle.ts` | Working | Pull a bundle and access files, prompts, and skills | -| `basics/resolve-bundle.ts` | Working | Resolve metadata without downloading | -| `basics/verify-and-lock-bundle.ts` | Working | Verify SHA-256 integrity and write a lockfile | -| `claude/install-project-skills.ts` | Working | Install skills into `.claude/skills/` | -| `claude/export-plugin.ts` | Working | Export a Claude Code plugin directory | -| `openai/local-shell-skill.ts` | Working | Export a skill as local files for OpenAI Agents | -| `openai/hosted-inline-skill.ts` | Working | Export a skill as an inline base64 ZIP | -| `openai/local-shell-agent.ts` | Working | Full agent with local shell skill via `@openai/agents` | -| `openai/container-inline-agent.ts` | Working | Agent with inline skill in `container_auto` | -| `openai/container-skill-ref.ts` | Working | Upload a skill and use as a `skill_reference` | -| `ide/install-vscode-skills.ts` | Working | Install skills into a VS Code skill tree | +| File | Bundle | Status | Description | +|------|--------|--------|-------------| +| `basics/pull-bundle.ts` | `code-review-kit` | Working | Pull a bundle and access files, prompts, and skills | +| `basics/resolve-bundle.ts` | `code-review-kit` | Working | Resolve metadata without downloading | +| `basics/verify-and-lock-bundle.ts` | `code-review-kit` | Working | Verify SHA-256 integrity and write a lockfile | +| `basics/explore-all-assets.ts` | `agent-toolkit` | Working | Enumerate skills, prompts, toolsets, and agent specs | +| `basics/select-and-materialize.ts` | `agent-toolkit` | Working | Filter a bundle to a subset and write to disk | +| `basics/cache-management.ts` | `code-review-kit` | Working | Inspect, invalidate, and clean the local cache | +| `basics/configure-client.ts` | `prompt-library` | Working | Configure the default client, binary and stream access | +| `claude/install-project-skills.ts` | `code-review-kit` | Working | Install skills into `.claude/skills/` | +| `claude/export-plugin.ts` | `code-review-kit` | Working | Export a Claude Code plugin directory | +| `openai/local-shell-skill.ts` | `code-review-kit` | Working | Export a skill as local files for OpenAI Agents | +| `openai/hosted-inline-skill.ts` | `code-review-kit` | Working | Export a skill as an inline base64 ZIP | +| `openai/local-shell-agent.ts` | `code-review-kit` | Working | Full agent with local shell skill via `@openai/agents` | +| `openai/container-inline-agent.ts` | `code-review-kit` | Working | Agent with inline skill in `container_auto` | +| `openai/container-skill-ref.ts` | `code-review-kit` | Working | Upload a skill and use as a `skill_reference` | +| `ide/install-vscode-skills.ts` | `code-review-kit` | Working | Install skills into a VS Code skill tree | + +## Example bundles + +These examples use public bundles from the [`musher-examples`](https://hub.musher.dev/) namespace: + +| Bundle | Version | Asset Types | +|--------|---------|-------------| +| `musher-examples/code-review-kit` | 1.2.0 | Skills, Prompts | +| `musher-examples/agent-toolkit` | 2.0.0 | Skills, Prompts, Toolsets, Agent Specs, Configs, Rules | +| `musher-examples/prompt-library` | 1.2.0 | Prompts, Toolsets, Agent Specs | ## Runtime packages for integration examples @@ -41,3 +57,16 @@ npx tsx examples/basics/pull-bundle.ts | Claude | `@anthropic-ai/claude-agent-sdk` | | OpenAI (agents) | `@openai/agents` | | OpenAI (API client) | `openai` | + +## Troubleshooting + +| Problem | Fix | +|---------|-----| +| `AuthenticationError` | Set `MUSHER_API_KEY` in your environment or run `musher login` | +| `NotFoundError` | Check the bundle ref — examples use the `musher-examples/` namespace | +| `TimeoutError` or network failures | Check connectivity; override timeout via `new MusherClient({ timeout: 120000 })` | + +## See also + +- [SDK reference](../packages/musher/README.md) — full API documentation +- [Security policy](../SECURITY.md) — reporting vulnerabilities diff --git a/examples/basics/cache-management.ts b/examples/basics/cache-management.ts new file mode 100644 index 0000000..a2093b0 --- /dev/null +++ b/examples/basics/cache-management.ts @@ -0,0 +1,53 @@ +/** + * Inspect and manage the local bundle cache. + * + * After pulling bundles, `client.cache` provides methods to list + * entries, check freshness, view statistics, and clean up stale data. + * + * Prerequisites: + * export MUSHER_API_KEY="mush_..." + * + * Run: + * npx tsx examples/basics/cache-management.ts + */ + +import { MusherClient } from "@musher-dev/musher-sdk"; + +const client = new MusherClient(); + +// Pull a bundle so there is something in the cache +await client.pull("musher-examples/code-review-kit:1.2.0"); +console.log("Pulled code-review-kit into cache.\n"); + +// Check if a specific bundle is cached +const status = await client.cache.has("musher-examples", "code-review-kit", "1.2.0"); +console.log("Cache status for code-review-kit:1.2.0:"); +console.log(` cached: ${status.cached}`); +console.log(` fresh: ${status.fresh}`); + +// List all cached bundles +const entries = await client.cache.list(); +console.log(`\nCached bundles (${entries.length}):`); +for (const entry of entries) { + console.log( + ` ${entry.namespace}/${entry.slug}:${entry.version}` + + ` fresh=${entry.fresh} size=${entry.sizeBytes} bytes`, + ); +} + +// Aggregate statistics +const stats = await client.cache.stats(); +console.log("\nCache statistics:"); +console.log( + ` entries: ${stats.entryCount} (${stats.freshCount} fresh, ${stats.staleCount} stale)`, +); +console.log(` blobs: ${stats.blobCount} (${stats.blobSizeBytes} bytes)`); +console.log(` refs: ${stats.refCount}`); + +// Mark a bundle as stale (next pull will re-fetch) +const invalidated = await client.cache.invalidate("musher-examples", "code-review-kit", "1.2.0"); +console.log(`\nInvalidated ${invalidated} entry (now stale).`); + +// Clean up expired entries +await client.cache.clean(); +console.log("Cleaned expired entries."); diff --git a/examples/basics/configure-client.ts b/examples/basics/configure-client.ts new file mode 100644 index 0000000..faecba8 --- /dev/null +++ b/examples/basics/configure-client.ts @@ -0,0 +1,50 @@ +/** + * Configure the module-level client and access binary content. + * + * `configure()` sets options for the default client used by the + * top-level `pull()` and `resolve()` functions. This example also + * demonstrates `FileHandle.bytes()` and `FileHandle.stream()` for + * binary-safe content access. + * + * Prerequisites: + * export MUSHER_API_KEY="mush_..." + * + * Run: + * npx tsx examples/basics/configure-client.ts + */ + +import { configure, getClient, pull } from "@musher-dev/musher-sdk"; + +// Configure the default client with a custom cache directory +configure({ cacheDir: "/tmp/musher-examples-cache" }); + +// Verify the configured client is returned by getClient() +const client = getClient(); +console.log(`Client configured (cache API available: ${typeof client.cache.list === "function"}).`); + +// pull() uses the configured client automatically +const bundle = await pull("musher-examples/prompt-library:1.2.0"); + +// List all prompts in the bundle +console.log(`\nPrompts in ${bundle.ref.toString()}:`); +for (const prompt of bundle.prompts()) { + console.log(` ${prompt.name} (${prompt.file().sizeBytes} bytes)`); +} + +// Demonstrate binary access via bytes() +const file = bundle.prompt("system").file(); +const bytes = file.bytes(); +console.log(`\nBinary access — "system" prompt: ${bytes.byteLength} bytes (Uint8Array)`); + +// Demonstrate streaming access via stream() +const stream = file.stream(); +const reader = stream.getReader(); +let totalStreamBytes = 0; +while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + totalStreamBytes += value.byteLength; +} +console.log(`Stream access — "system" prompt: ${totalStreamBytes} bytes read`); diff --git a/examples/basics/explore-all-assets.ts b/examples/basics/explore-all-assets.ts new file mode 100644 index 0000000..8160b36 --- /dev/null +++ b/examples/basics/explore-all-assets.ts @@ -0,0 +1,49 @@ +/** + * Explore every asset type in a bundle. + * + * The `musher-examples/agent-toolkit` bundle contains skills, prompts, + * toolsets, agent specs, configs, and rules — ideal for learning how + * to enumerate and inspect all asset types via the SDK. + * + * Prerequisites: + * export MUSHER_API_KEY="mush_..." + * + * Run: + * npx tsx examples/basics/explore-all-assets.ts + */ + +import { pull } from "@musher-dev/musher-sdk"; + +const bundle = await pull("musher-examples/agent-toolkit:2.0.0"); + +// --- Skills --- +console.log("Skills:"); +for (const skill of bundle.skills()) { + const meta = skill.metadata(); + console.log(` ${skill.name} — ${meta?.description ?? "(no description)"}`); + console.log(` files: ${skill.files().length}`); +} + +// --- Prompts --- +console.log("\nPrompts:"); +for (const prompt of bundle.prompts()) { + console.log(` ${prompt.name} (${prompt.file().sizeBytes} bytes)`); +} + +// --- Toolsets --- +console.log("\nToolsets:"); +for (const toolset of bundle.toolsets()) { + const parsed = JSON.parse(toolset.content()); + console.log(` ${toolset.name} — ${parsed.description ?? ""}`); +} + +// --- Agent Specs --- +console.log("\nAgent Specs:"); +for (const spec of bundle.agentSpecs()) { + const parsed = JSON.parse(spec.content()); + console.log(` ${spec.name} — model: ${parsed.model}, skills: [${parsed.skills?.join(", ")}]`); +} + +// Access a specific toolset by name +const defaultTools = bundle.toolset("default-tools"); +console.log(`\nToolset "default-tools" content:\n${defaultTools.content()}`); diff --git a/examples/basics/select-and-materialize.ts b/examples/basics/select-and-materialize.ts new file mode 100644 index 0000000..3530bbb --- /dev/null +++ b/examples/basics/select-and-materialize.ts @@ -0,0 +1,55 @@ +/** + * Filter a bundle to a subset and write it to disk. + * + * `bundle.select()` creates a lazy filtered view (Selection) that + * includes only the named assets. `selection.materialize()` writes + * those files to a target directory preserving logical paths. + * + * Prerequisites: + * export MUSHER_API_KEY="mush_..." + * + * Run: + * npx tsx examples/basics/select-and-materialize.ts + */ + +import { pull } from "@musher-dev/musher-sdk"; + +const bundle = await pull("musher-examples/agent-toolkit:2.0.0"); + +// Select a subset: one skill, one prompt, and one toolset +const selection = bundle.select({ + skills: ["explaining-architecture"], + prompts: ["system"], + toolsets: ["default-tools"], +}); + +console.log("Selected files:"); +for (const file of selection.files()) { + console.log(` ${file.logicalPath} (${file.assetType})`); +} + +console.log( + `\nSkills in selection: ${selection + .skills() + .map((s) => s.name) + .join(", ")}`, +); +console.log( + `Prompts in selection: ${selection + .prompts() + .map((p) => p.name) + .join(", ")}`, +); +console.log( + `Toolsets in selection: ${selection + .toolsets() + .map((t) => t.name) + .join(", ")}`, +); + +// Write the selected files to disk +const written = await selection.materialize("./agent-toolkit-subset"); +console.log(`\nMaterialized ${written.length} file(s) to ./agent-toolkit-subset/`); +for (const path of written) { + console.log(` ${path}`); +} diff --git a/examples/package.json b/examples/package.json index 401c4d0..75e2e5c 100644 --- a/examples/package.json +++ b/examples/package.json @@ -10,6 +10,6 @@ "@openai/agents": "^0.1.0", "@types/node": "^22.0.0", "openai": "^4.0.0", - "typescript": "^5.7.0" + "typescript": "^5.9.0" } } diff --git a/package.json b/package.json index abc1f9d..2dd0676 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,11 @@ "clean": "pnpm -r clean" }, "devDependencies": { - "@biomejs/biome": "^1.9.4", + "@biomejs/biome": "^2.0.0", "tsx": "^4.21.0", - "typescript": "^5.7.0" + "typescript": "^5.9.0" }, - "packageManager": "pnpm@9.15.0", + "packageManager": "pnpm@10.33.0", "engines": { "node": ">=20" } diff --git a/packages/musher/README.md b/packages/musher/README.md index 5b2457c..3977e62 100644 --- a/packages/musher/README.md +++ b/packages/musher/README.md @@ -1,13 +1,39 @@ # @musher-dev/musher-sdk +[![npm](https://img.shields.io/npm/v/@musher-dev/musher-sdk)](https://www.npmjs.com/package/@musher-dev/musher-sdk) +[![CI](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/musher-dev/typescript-sdk/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE) +![Node >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen) + Official TypeScript SDK for the [Musher](https://musher.dev) platform. Pull, cache, and load bundled AI agent assets — skills, prompts, toolsets, and agent specs — from the Musher registry. +- **One function to get started** — `pull()` resolves, downloads, verifies, and caches a bundle +- **Content-addressable disk cache** — SHA-256 integrity checks, deduplication, and TTL-based freshness +- **Typed asset handles** — first-class accessors for skills, prompts, toolsets, and agent specs +- **Platform adapters** — drop bundles into Claude Code, OpenAI Agents, or VS Code with one call +- **Lightweight** — single runtime dependency (`zod`); ESM + CJS dual output + ## Install ```bash npm install @musher-dev/musher-sdk ``` +## Authentication + +Set your API key as an environment variable (recommended for CI/CD): + +```bash +export MUSHER_API_KEY="msk_..." +``` + +The SDK resolves credentials in this order: + +1. Explicit `apiKey` in `ClientConfig` +2. `MUSHER_API_KEY` environment variable +3. OS keyring (macOS Keychain, Linux `secret-tool`) +4. Credential file at `{data}/credentials/{host}/api-key` (must be `chmod 600`) + ## Usage ### Pull and access a bundle @@ -18,14 +44,14 @@ import { pull } from "@musher-dev/musher-sdk"; const bundle = await pull("acme/code-review-kit:1.2.0"); // Typed handle access -bundle.prompt("system").content(); // prompt text -bundle.skill("lint-rules").files(); // skill files -bundle.toolset("review-tools").content(); // toolset definition -bundle.agentSpec("reviewer").content(); // agent spec +bundle.prompt("system").content(); // prompt text +bundle.skill("lint-rules").files(); // skill files +bundle.toolset("review-tools").content(); // toolset JSON +bundle.agentSpec("reviewer").content(); // agent spec // Raw file access bundle.file("prompts/system.md")?.text(); -bundle.files(); // all FileHandle[] +bundle.files(); // all FileHandle[] ``` ### Resolve metadata only @@ -37,10 +63,41 @@ const meta = await resolve("acme/code-review-kit:1.2.0"); console.log(meta.version, meta.ref); ``` +### Select and materialize + +Filter a bundle to a subset and write it to disk: + +```typescript +const selection = bundle.select({ + skills: ["lint-rules"], + prompts: ["system"], +}); + +selection.files(); // only matching FileHandle[] +await selection.materialize("./output"); // write to disk +``` + +### Cache management + +```typescript +import { MusherClient } from "@musher-dev/musher-sdk"; + +const client = new MusherClient(); + +const stats = await client.cache.stats(); +console.log(stats.entryCount, stats.blobSizeBytes); + +const entries = await client.cache.list(); +await client.cache.invalidate("acme", "code-review-kit"); +await client.cache.clean(); // remove expired entries +``` + ### Verify integrity and lock ```typescript -const result = bundle.verify(); // SHA-256 check on every file +const result = bundle.verify(); // SHA-256 check on every file +console.log(result.ok, result.errors); + await bundle.writeLockfile("./musher-lock.json"); ``` @@ -64,20 +121,70 @@ import { installClaudeSkills, exportClaudePlugin, exportOpenAILocalSkill, - exportOpenAIInlineSkill, installVSCodeSkills, } from "@musher-dev/musher-sdk"; -// Claude Code — install skills into .claude/skills// +// Claude Code — install skills into .claude/skills/ await installClaudeSkills(bundle, process.cwd()); -// OpenAI — export a skill for local shell agents -const local = await exportOpenAILocalSkill(bundle.skill("lint-rules"), "./skills"); +// Claude Code — export as a plugin directory +await exportClaudePlugin(bundle, { targetDir: "./my-plugin" }); + +// OpenAI Agents — export a skill for local shell agents +await exportOpenAILocalSkill(bundle.skill("lint-rules"), "./skills"); // VS Code — install into .agents/skills/ await installVSCodeSkills(bundle, process.cwd()); ``` +## Error handling + +All errors extend `MusherError` for unified catching: + +``` +MusherError +├── ApiError (.status, .problem) +│ ├── NotFoundError +│ ├── AuthenticationError +│ ├── ForbiddenError +│ ├── ValidationError (.errors) +│ └── RateLimitError (.retryAfter) +├── NetworkError +│ └── TimeoutError +├── CacheError +│ └── IntegrityError (.expected, .actual) +├── SchemaError +└── BundleAssetNotFoundError (.assetType, .assetName) +``` + +```typescript +import { pull, MusherError, NotFoundError } from "@musher-dev/musher-sdk"; + +try { + const bundle = await pull("acme/missing-bundle:1.0.0"); +} catch (err) { + if (err instanceof NotFoundError) { + console.error("Bundle not found:", err.problem.detail); + } else if (err instanceof MusherError) { + console.error("Musher error:", err.message); + } +} +``` + +## Environment variables + +| Variable | Description | +|----------|-------------| +| `MUSHER_API_KEY` | API key for authentication | +| `MUSHER_API_URL` | Override API base URL (default: `https://api.musher.dev`) | +| `MUSHER_HOME` | Override all directories: `{MUSHER_HOME}/{cache,config,data,state}` | +| `MUSHER_CACHE_HOME` | Override cache directory (takes precedence over `MUSHER_HOME`) | +| `MUSHER_CONFIG_HOME` | Override config directory | +| `MUSHER_DATA_HOME` | Override data directory | +| `MUSHER_STATE_HOME` | Override state directory | + +Default directories follow platform conventions: XDG on Linux, `~/Library` on macOS, `%LOCALAPPDATA%` on Windows. + ## Key exports | Export | Kind | Description | @@ -85,15 +192,25 @@ await installVSCodeSkills(bundle, process.cwd()); | `pull` | function | Pull a bundle (resolve + download + verify + cache) | | `resolve` | function | Resolve bundle metadata without downloading | | `configure` | function | Set default client config for convenience functions | -| `MusherClient` | class | Client with custom config, cache management | +| `getClient` | function | Get the global `MusherClient` singleton | +| `MusherClient` | class | Client with custom config, cache, and bundle operations | | `Bundle` | class | Typed bundle with handle access and verification | | `BundleRef` | class | Parse and represent `namespace/slug:version` refs | | `Selection` | class | Lazy filtered view over a bundle | -| `FileHandle` | class | File content access (text, bytes, stream) | +| `FileHandle` | class | File content access (`.text()`, `.bytes()`, `.stream()`) | | `SkillHandle` | class | Skill file grouping with definition access | | `PromptHandle` | class | Single-file prompt with `.content()` | | `ToolsetHandle` | class | Single-file toolset with `.content()` | | `AgentSpecHandle` | class | Single-file agent spec with `.content()` | +| `MusherError` | class | Base error class for all SDK errors | +| `installClaudeSkills` | function | Install skills into `.claude/skills/` | +| `exportClaudePlugin` | function | Export a Claude Code plugin directory | +| `exportOpenAILocalSkill` | function | Export a skill for OpenAI local shell agents | +| `exportOpenAIInlineSkill` | function | Export a skill as inline base64 ZIP | +| `installVSCodeSkills` | function | Install skills into VS Code skill tree | +| `resolveMusherDirs` | function | Resolve platform-specific Musher directories | + +Types: `ClientConfig`, `CacheManager`, `CacheEntry`, `CacheStats`, `SelectionFilter`, `VerifyResult`, `BundleResolveOutput`, and [more](./src/types.ts). See [`examples/`](../../examples/) for runnable integration examples. diff --git a/packages/musher/package.json b/packages/musher/package.json index 1fe6b10..a82ab1d 100644 --- a/packages/musher/package.json +++ b/packages/musher/package.json @@ -19,7 +19,9 @@ "main": "./dist/index.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", - "files": ["dist"], + "files": [ + "dist" + ], "scripts": { "build": "tsup", "check": "pnpm check:format && pnpm check:lint && pnpm check:types && pnpm check:test", @@ -37,13 +39,14 @@ }, "devDependencies": { "@arethetypeswrong/cli": "^0.18.2", - "@biomejs/biome": "^1.9.4", + "@biomejs/biome": "^2.0.0", "@types/node": "^25.5.0", + "@vitest/coverage-v8": "^3.2.4", "knip": "^6.0.1", "publint": "^0.3.18", "tsup": "^8.3.0", - "typescript": "^5.7.0", - "vitest": "^2.1.0" + "typescript": "^5.9.0", + "vitest": "^3.2.0" }, "engines": { "node": ">=20" @@ -53,5 +56,11 @@ "url": "git+https://github.com/musher-dev/typescript-sdk.git", "directory": "packages/musher" }, - "keywords": ["musher", "bundle", "sdk", "ai", "agent"] + "keywords": [ + "musher", + "bundle", + "sdk", + "ai", + "agent" + ] } diff --git a/packages/musher/src/bundle.ts b/packages/musher/src/bundle.ts index 1b77e0d..808f7bd 100644 --- a/packages/musher/src/bundle.ts +++ b/packages/musher/src/bundle.ts @@ -8,6 +8,7 @@ import { createHash } from "node:crypto"; import { mkdir, writeFile } from "node:fs/promises"; import { dirname } from "node:path"; +import { BundleAssetNotFoundError } from "./errors.js"; import { AgentSpecHandle, FileHandle, @@ -17,7 +18,7 @@ import { } from "./handles/index.js"; import { BundleRef } from "./ref.js"; import { Selection } from "./selection.js"; -import type { BundleResolveOutput, LoadedAsset, SelectionFilter, VerifyResult } from "./types.js"; +import type { BundleResolveOutput, SelectionFilter, VerifyResult } from "./types.js"; export class Bundle { readonly ref: BundleRef; @@ -119,7 +120,7 @@ export class Bundle { skill(name: string): SkillHandle { const h = this._skills.get(name); if (!h) { - throw new Error(`Skill "${name}" not found in bundle`); + throw new BundleAssetNotFoundError("Skill", name); } return h; } @@ -131,7 +132,7 @@ export class Bundle { prompt(name: string): PromptHandle { const h = this._prompts.get(name); if (!h) { - throw new Error(`Prompt "${name}" not found in bundle`); + throw new BundleAssetNotFoundError("Prompt", name); } return h; } @@ -143,7 +144,7 @@ export class Bundle { toolset(name: string): ToolsetHandle { const h = this._toolsets.get(name); if (!h) { - throw new Error(`Toolset "${name}" not found in bundle`); + throw new BundleAssetNotFoundError("Toolset", name); } return h; } @@ -155,7 +156,7 @@ export class Bundle { agentSpec(name: string): AgentSpecHandle { const h = this._agentSpecs.get(name); if (!h) { - throw new Error(`AgentSpec "${name}" not found in bundle`); + throw new BundleAssetNotFoundError("AgentSpec", name); } return h; } @@ -217,36 +218,6 @@ export class Bundle { const { installVSCodeSkills } = await import("./adapters/vscode.js"); return installVSCodeSkills(this, dir, opts); } - - // -- Deprecated compat -- - - /** @deprecated Use `file(path)` instead. */ - getAsset(path: string): LoadedAsset | undefined { - const fh = this._files.get(path); - if (!fh) { - return undefined; - } - return { - logicalPath: fh.logicalPath, - assetType: fh.assetType, - content: fh.text(), - sha256: fh.sha256, - mediaType: fh.mediaType, - }; - } - - /** @deprecated Use `files().filter(...)` instead. */ - getAssetsByType(type: string): LoadedAsset[] { - return [...this._files.values()] - .filter((fh) => fh.assetType === type) - .map((fh) => ({ - logicalPath: fh.logicalPath, - assetType: fh.assetType, - content: fh.text(), - sha256: fh.sha256, - mediaType: fh.mediaType, - })); - } } /** Extract skill name from logical path: "skills/foo/SKILL.md" → "foo" */ diff --git a/packages/musher/src/cache.ts b/packages/musher/src/cache.ts index c568cd5..73100a8 100644 --- a/packages/musher/src/cache.ts +++ b/packages/musher/src/cache.ts @@ -13,11 +13,11 @@ import { createHash, randomUUID } from "node:crypto"; import { existsSync } from "node:fs"; -import { mkdir, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises"; +import { mkdir, readdir, readFile, rename, rm, stat, unlink, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { Bundle } from "./bundle.js"; import { CacheError, IntegrityError } from "./errors.js"; -import type { BundleResolveOutput, CacheEntry, CacheStats, CachedBundle } from "./types.js"; +import type { BundleResolveOutput, CacheEntry, CacheStats } from "./types.js"; const JSON_EXT_RE = /\.json$/; @@ -190,28 +190,17 @@ export class BundleCache { } /** Write a resolved bundle and its assets to the cache. */ - async write( - manifest: BundleResolveOutput, - assets: Map, - ): Promise { + async write(manifest: BundleResolveOutput, assets: Map): Promise { try { await this.ensureCacheDirTag(); // Write blobs (content-addressable) for (const [, content] of assets) { - const buf = typeof content === "string" ? Buffer.from(content, "utf-8") : content; - await this.writeBlob(buf); + await this.writeBlob(content); } // Write manifest + metadata await this.writeManifest(manifest); - - return { - ref: manifest.ref, - version: manifest.version, - cacheDir: this.manifestDir(manifest.namespace, manifest.slug), - manifest, - }; } catch (error) { throw new CacheError( `Failed to write cache: ${error instanceof Error ? error.message : String(error)}`, @@ -528,9 +517,6 @@ export class BundleCache { // Garbage-collect unreferenced blobs await this.gcBlobs(referencedDigests); - - // Remove legacy bundles/ directory if present - await this.removeLegacy(); } catch (error) { throw new CacheError( `Failed to clean cache: ${error instanceof Error ? error.message : String(error)}`, @@ -542,7 +528,7 @@ export class BundleCache { /** Remove all cached data. */ async purge(): Promise { try { - const dirs = ["manifests", "refs", "blobs", "temp", "bundles"]; + const dirs = ["manifests", "refs", "blobs", "temp"]; for (const dir of dirs) { const p = join(this.cacheDir, dir); if (existsSync(p)) { @@ -668,14 +654,6 @@ export class BundleCache { } } } - - /** Remove legacy bundles/ directory if present. */ - private async removeLegacy(): Promise { - const legacyDir = join(this.cacheDir, "bundles"); - if (existsSync(legacyDir)) { - await rm(legacyDir, { recursive: true, force: true }); - } - } } // -- Helpers ------------------------------------------------------------------ diff --git a/packages/musher/src/client.ts b/packages/musher/src/client.ts index 7070890..1393092 100644 --- a/packages/musher/src/client.ts +++ b/packages/musher/src/client.ts @@ -21,8 +21,6 @@ import type { PullBundleVersionOutput, } from "./types.js"; -let _loadDeprecationWarned = false; - export class MusherClient { readonly bundles: BundlesResource; @@ -151,46 +149,6 @@ export class MusherClient { return resolved; } - /** - * @deprecated Use `pull()` instead. This method will be removed in a future version. - * - * Load a bundle into memory. Checks cache first (TTL-aware), pulls if stale. - */ - async load(ref: string, version?: string): Promise { - if (!_loadDeprecationWarned) { - _loadDeprecationWarned = true; - process.emitWarning( - "MusherClient.load() is deprecated. Use pull() instead.", - "DeprecationWarning", - ); - } - - const parsed = BundleRef.parse(ref); - let resolvedVersion = version ?? parsed.version; - - // For unversioned, non-digest refs, try the ref cache first - if (!(resolvedVersion || parsed.digest)) { - const cachedVersion = await this._cache.resolveRef(parsed.namespace, parsed.slug, "latest"); - if (cachedVersion) { - resolvedVersion = cachedVersion; - } - } - - // If version is known, check manifest cache - if (resolvedVersion) { - const fresh = await this._cache.isFresh(parsed.namespace, parsed.slug, resolvedVersion); - if (fresh) { - const loaded = await this._cache.load(parsed.namespace, parsed.slug, resolvedVersion); - if (loaded) { - return loaded; - } - } - } - - // Pull (resolve + download + cache) - return this.pull(ref, version); - } - /** * Pull content via the :pull endpoint with automatic fallback. * diff --git a/packages/musher/src/config.ts b/packages/musher/src/config.ts index 70fd6da..9f910f2 100644 --- a/packages/musher/src/config.ts +++ b/packages/musher/src/config.ts @@ -20,9 +20,9 @@ export interface ClientConfig { manifestTtlSeconds?: number; /** Ref cache TTL in seconds. Default: 300 (5 minutes) */ refTtlSeconds?: number; - /** Request timeout in milliseconds. Default: 30000 */ + /** Request timeout in milliseconds. Default: 60000 */ timeout?: number; - /** Number of retries on transient failures. Default: 2 */ + /** Number of retries on transient failures. Default: 3 */ retries?: number; } diff --git a/packages/musher/src/errors.ts b/packages/musher/src/errors.ts index bf28a64..9d79ec8 100644 --- a/packages/musher/src/errors.ts +++ b/packages/musher/src/errors.ts @@ -1,13 +1,13 @@ /** * Error hierarchy for the Musher SDK. * - * All errors extend MushError so consumers can catch the base class. + * All errors extend MusherError so consumers can catch the base class. */ -export class MushError extends Error { +export class MusherError extends Error { constructor(message: string, options?: ErrorOptions) { super(message, options); - this.name = "MushError"; + this.name = "MusherError"; } } @@ -22,7 +22,7 @@ export interface ProblemDetail { traceId?: string | undefined; } -export class ApiError extends MushError { +export class ApiError extends MusherError { readonly status: number; readonly problem: ProblemDetail; @@ -80,7 +80,7 @@ export class RateLimitError extends ApiError { // -- Network errors ----------------------------------------------------------- -export class NetworkError extends MushError { +export class NetworkError extends MusherError { constructor(message: string, options?: ErrorOptions) { super(message, options); this.name = "NetworkError"; @@ -96,7 +96,7 @@ export class TimeoutError extends NetworkError { // -- Cache errors ------------------------------------------------------------- -export class CacheError extends MushError { +export class CacheError extends MusherError { constructor(message: string, options?: ErrorOptions) { super(message, options); this.name = "CacheError"; @@ -116,9 +116,22 @@ export class IntegrityError extends CacheError { // -- Schema errors ------------------------------------------------------------ -export class SchemaError extends MushError { +export class SchemaError extends MusherError { constructor(message: string, options?: ErrorOptions) { super(message, options); this.name = "SchemaError"; } } + +// -- Bundle errors ------------------------------------------------------------ + +export class BundleAssetNotFoundError extends MusherError { + constructor( + readonly assetType: string, + readonly assetName: string, + options?: ErrorOptions, + ) { + super(`${assetType} "${assetName}" not found in bundle`, options); + this.name = "BundleAssetNotFoundError"; + } +} diff --git a/packages/musher/src/http.ts b/packages/musher/src/http.ts index 7960d2b..3f8134e 100644 --- a/packages/musher/src/http.ts +++ b/packages/musher/src/http.ts @@ -5,6 +5,7 @@ import type { z } from "zod"; const TRAILING_SLASH_RE = /\/$/; + import type { ResolvedConfig } from "./config.js"; import { ApiError, diff --git a/packages/musher/src/index.ts b/packages/musher/src/index.ts index 5442d38..1a7e0ae 100644 --- a/packages/musher/src/index.ts +++ b/packages/musher/src/index.ts @@ -1,27 +1,4 @@ // -- Client ------------------------------------------------------------------- -export { MusherClient } from "./client.js"; -export type { ClientConfig } from "./config.js"; - -// -- Paths -------------------------------------------------------------------- -export { resolveMusherDirs } from "./paths.js"; -export type { MusherDirs } from "./paths.js"; - -// -- Core classes ------------------------------------------------------------- -export { Bundle } from "./bundle.js"; -export { BundleRef } from "./ref.js"; -export { Selection } from "./selection.js"; - -// -- Handles ------------------------------------------------------------------ -export { - AgentSpecHandle, - FileHandle, - PromptHandle, - SkillHandle, - ToolsetHandle, -} from "./handles/index.js"; - -// -- Frontmatter -------------------------------------------------------------- -export { extractDescription, parseFrontmatter, type FrontmatterResult } from "./frontmatter.js"; // -- Adapters ----------------------------------------------------------------- export { @@ -33,18 +10,21 @@ export { type OpenAIInlineSkill, type OpenAILocalSkill, } from "./adapters/index.js"; - +// -- Core classes ------------------------------------------------------------- +export { Bundle } from "./bundle.js"; +export { MusherClient } from "./client.js"; +export type { ClientConfig } from "./config.js"; // -- Convenience functions ---------------------------------------------------- export { configure, getClient, pull, resolve } from "./convenience.js"; - // -- Errors ------------------------------------------------------------------- export { ApiError, AuthenticationError, + BundleAssetNotFoundError, CacheError, ForbiddenError, IntegrityError, - MushError, + MusherError, NetworkError, NotFoundError, type ProblemDetail, @@ -53,7 +33,21 @@ export { TimeoutError, ValidationError, } from "./errors.js"; +// -- Frontmatter -------------------------------------------------------------- +export { extractDescription, type FrontmatterResult, parseFrontmatter } from "./frontmatter.js"; +// -- Handles ------------------------------------------------------------------ +export { + AgentSpecHandle, + FileHandle, + PromptHandle, + SkillHandle, + ToolsetHandle, +} from "./handles/index.js"; +export type { MusherDirs } from "./paths.js"; +// -- Paths -------------------------------------------------------------------- +export { resolveMusherDirs } from "./paths.js"; +export { BundleRef } from "./ref.js"; // -- Schemas ------------------------------------------------------------------ export { AssetDetailOutputSchema, @@ -76,6 +70,7 @@ export { PullBundleVersionOutputSchema, paginatedSchema, } from "./schemas/index.js"; +export { Selection } from "./selection.js"; // -- Types -------------------------------------------------------------------- export type { @@ -91,9 +86,6 @@ export type { CacheEntry, CacheManager, CacheStats, - CachedBundle, - LoadedAsset, - LoadedBundle, ManifestAssetOutput, ManifestDetailOutput, Paginated, diff --git a/packages/musher/src/ref.ts b/packages/musher/src/ref.ts index 25ae7de..46e2131 100644 --- a/packages/musher/src/ref.ts +++ b/packages/musher/src/ref.ts @@ -7,7 +7,7 @@ * namespace/slug@sha256:digest */ -import { MushError } from "./errors.js"; +import { MusherError } from "./errors.js"; const REF_PATTERN = /^([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(?::(.+)|@sha256:([a-fA-F0-9]+))?$/; @@ -28,7 +28,7 @@ export class BundleRef { static parse(ref: string): BundleRef { const match = ref.match(REF_PATTERN); if (!match) { - throw new MushError( + throw new MusherError( `Invalid bundle ref "${ref}": expected "namespace/slug", "namespace/slug:version", or "namespace/slug@sha256:digest"`, ); } diff --git a/packages/musher/src/resources/bundles.ts b/packages/musher/src/resources/bundles.ts index 29e7bec..caa7bb6 100644 --- a/packages/musher/src/resources/bundles.ts +++ b/packages/musher/src/resources/bundles.ts @@ -19,8 +19,8 @@ import type { BundleResolveOutput, BundleVersionDetailOutput, BundleVersionSummaryOutput, - PaginateParams, Paginated, + PaginateParams, PullBundleVersionOutput, } from "../types.js"; diff --git a/packages/musher/src/schemas/index.ts b/packages/musher/src/schemas/index.ts index fc70c32..021038b 100644 --- a/packages/musher/src/schemas/index.ts +++ b/packages/musher/src/schemas/index.ts @@ -1,3 +1,5 @@ +export { AssetDetailOutputSchema, AssetSummaryOutputSchema } from "./asset.js"; +export { BundleDetailOutputSchema, BundleOutputSchema } from "./bundle.js"; export { AssetType, BundleSourceType, @@ -7,10 +9,6 @@ export { paginatedSchema, } from "./common.js"; -export { AssetDetailOutputSchema, AssetSummaryOutputSchema } from "./asset.js"; - -export { BundleDetailOutputSchema, BundleOutputSchema } from "./bundle.js"; - export { BundleLayerOutputSchema, BundleManifestOutputSchema, diff --git a/packages/musher/src/types.ts b/packages/musher/src/types.ts index da1eb84..7a7341d 100644 --- a/packages/musher/src/types.ts +++ b/packages/musher/src/types.ts @@ -63,38 +63,6 @@ export type PullBundleVersionOutput = z.infer; - getAsset(path: string): LoadedAsset | undefined; - getAssetsByType(type: string): LoadedAsset[]; -} - -/** @deprecated Use `Bundle` class instead. */ -export interface CachedBundle { - ref: string; - version: string; - cacheDir: string; - manifest: BundleResolveOutput; -} - -// -- New types ---------------------------------------------------------------- - export interface VerifyResult { ok: boolean; errors: Array<{ path: string; expected: string; actual: string }>; diff --git a/packages/musher/tests/bundle.test.ts b/packages/musher/tests/bundle.test.ts index 766b247..a855bed 100644 --- a/packages/musher/tests/bundle.test.ts +++ b/packages/musher/tests/bundle.test.ts @@ -1,10 +1,10 @@ import { createHash } from "node:crypto"; -import { readFile } from "node:fs/promises"; -import { mkdtemp, rm } from "node:fs/promises"; +import { mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { Bundle } from "../src/bundle.js"; +import { BundleAssetNotFoundError } from "../src/errors.js"; import type { BundleResolveOutput } from "../src/types.js"; function sha(text: string): string { @@ -107,7 +107,7 @@ describe("Bundle", () => { it("skill() accessor", () => { const bundle = new Bundle(makeManifest(), makeContents()); expect(bundle.skill("review").name).toBe("review"); - expect(() => bundle.skill("nonexistent")).toThrow("not found"); + expect(() => bundle.skill("nonexistent")).toThrow(BundleAssetNotFoundError); }); it("groups prompts correctly", () => { @@ -145,21 +145,6 @@ describe("Bundle", () => { expect(result.errors[0]?.path).toBe("prompts/system.md"); }); - it("deprecated getAsset() still works", () => { - const bundle = new Bundle(makeManifest(), makeContents()); - const asset = bundle.getAsset("prompts/system.md"); - expect(asset?.content).toBe(PROMPT_CONTENT); - expect(asset?.assetType).toBe("prompt"); - }); - - it("deprecated getAssetsByType() still works", () => { - const bundle = new Bundle(makeManifest(), makeContents()); - const skills = bundle.getAssetsByType("skill"); - expect(skills).toHaveLength(2); - const configs = bundle.getAssetsByType("config"); - expect(configs).toHaveLength(0); - }); - describe("writeLockfile", () => { let tempDir: string; diff --git a/packages/musher/tests/cache.test.ts b/packages/musher/tests/cache.test.ts index b957116..f7b6591 100644 --- a/packages/musher/tests/cache.test.ts +++ b/packages/musher/tests/cache.test.ts @@ -1,5 +1,5 @@ import { existsSync } from "node:fs"; -import { mkdtemp, readFile, readdir, rm } from "node:fs/promises"; +import { mkdtemp, readdir, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; @@ -48,10 +48,7 @@ describe("BundleCache", () => { it("writes and loads a bundle via content-addressable blobs", async () => { const assets = new Map([["hello.txt", Buffer.from("Hello, World!")]]); - const cached = await cache.write(FIXTURE_MANIFEST, assets); - - expect(cached.ref).toBe("acme/test-bundle"); - expect(cached.version).toBe("1.0.0"); + await cache.write(FIXTURE_MANIFEST, assets); const loaded = await cache.load("acme", "test-bundle", "1.0.0"); expect(loaded).not.toBeNull(); @@ -65,15 +62,6 @@ describe("BundleCache", () => { expect(file?.assetType).toBe("prompt"); }); - it("accepts string values in write() for backwards compat", async () => { - const assets = new Map([["hello.txt", "Hello, World!"]]); - const cached = await cache.write(FIXTURE_MANIFEST, assets); - expect(cached.ref).toBe("acme/test-bundle"); - - const loaded = await cache.load("acme", "test-bundle", "1.0.0"); - expect(loaded?.file("hello.txt")?.text()).toBe("Hello, World!"); - }); - it("returns null for missing cache entry", async () => { const loaded = await cache.load("acme", "nonexistent", "1.0.0"); expect(loaded).toBeNull(); @@ -90,18 +78,6 @@ describe("BundleCache", () => { expect(stale).toBe(false); }); - it("deprecated getAssetsByType still works via Bundle", async () => { - const assets = new Map([["hello.txt", Buffer.from("Hello, World!")]]); - await cache.write(FIXTURE_MANIFEST, assets); - - const loaded = await cache.load("acme", "test-bundle", "1.0.0"); - const prompts = loaded?.getAssetsByType("prompt"); - expect(prompts).toHaveLength(1); - - const configs = loaded?.getAssetsByType("config"); - expect(configs).toHaveLength(0); - }); - it("purge removes all cached data", async () => { const assets = new Map([["hello.txt", Buffer.from("Hello, World!")]]); await cache.write(FIXTURE_MANIFEST, assets); diff --git a/packages/musher/tests/client.test.ts b/packages/musher/tests/client.test.ts index e99bdd6..04f392a 100644 --- a/packages/musher/tests/client.test.ts +++ b/packages/musher/tests/client.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; import { MusherClient } from "../src/client.js"; -import { MushError } from "../src/errors.js"; +import { MusherError } from "../src/errors.js"; const INVALID_BUNDLE_REF_RE = /Invalid bundle ref/; @@ -31,14 +31,9 @@ describe("MusherClient", () => { it("rejects invalid ref in pull()", async () => { const client = new MusherClient(); - await expect(client.pull("invalid-ref")).rejects.toThrow(MushError); - await expect(client.pull("/missing-namespace")).rejects.toThrow(MushError); - await expect(client.pull("")).rejects.toThrow(MushError); - }); - - it("rejects invalid ref in load()", async () => { - const client = new MusherClient(); - await expect(client.load("bad")).rejects.toThrow(MushError); + await expect(client.pull("invalid-ref")).rejects.toThrow(MusherError); + await expect(client.pull("/missing-namespace")).rejects.toThrow(MusherError); + await expect(client.pull("")).rejects.toThrow(MusherError); }); it("accepts versioned refs in pull()", async () => { diff --git a/packages/musher/tests/ref.test.ts b/packages/musher/tests/ref.test.ts index 2a45666..94c9cd0 100644 --- a/packages/musher/tests/ref.test.ts +++ b/packages/musher/tests/ref.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { MushError } from "../src/errors.js"; +import { MusherError } from "../src/errors.js"; import { BundleRef } from "../src/ref.js"; describe("BundleRef", () => { @@ -48,10 +48,10 @@ describe("BundleRef", () => { }); it("rejects invalid refs", () => { - expect(() => BundleRef.parse("invalid")).toThrow(MushError); - expect(() => BundleRef.parse("too/many/parts")).toThrow(MushError); - expect(() => BundleRef.parse("/missing")).toThrow(MushError); - expect(() => BundleRef.parse("")).toThrow(MushError); + expect(() => BundleRef.parse("invalid")).toThrow(MusherError); + expect(() => BundleRef.parse("too/many/parts")).toThrow(MusherError); + expect(() => BundleRef.parse("/missing")).toThrow(MusherError); + expect(() => BundleRef.parse("")).toThrow(MusherError); }); it("allows dots and underscores in slug", () => { diff --git a/packages/musher/vitest.config.ts b/packages/musher/vitest.config.ts index cd16adb..834845b 100644 --- a/packages/musher/vitest.config.ts +++ b/packages/musher/vitest.config.ts @@ -4,5 +4,16 @@ export default defineConfig({ test: { globals: true, include: ["tests/**/*.test.ts"], + coverage: { + provider: "v8", + include: ["src/**/*.ts"], + exclude: ["src/index.ts", "src/schemas/**"], + thresholds: { + branches: 80, + functions: 80, + lines: 80, + statements: 80, + }, + }, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d5a023..5b544b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,13 +9,13 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: ^1.9.4 - version: 1.9.4 + specifier: ^2.0.0 + version: 2.4.10 tsx: specifier: ^4.21.0 version: 4.21.0 typescript: - specifier: ^5.7.0 + specifier: ^5.9.0 version: 5.9.3 examples: @@ -33,7 +33,7 @@ importers: specifier: ^4.0.0 version: 4.104.0(ws@8.20.0)(zod@4.3.6) typescript: - specifier: ^5.7.0 + specifier: ^5.9.0 version: 5.9.3 packages/musher: @@ -46,11 +46,14 @@ importers: specifier: ^0.18.2 version: 0.18.2 '@biomejs/biome': - specifier: ^1.9.4 - version: 1.9.4 + specifier: ^2.0.0 + version: 2.4.10 '@types/node': specifier: ^25.5.0 version: 25.5.0 + '@vitest/coverage-v8': + specifier: ^3.2.4 + version: 3.2.4(vitest@3.2.4(@types/node@25.5.0)) knip: specifier: ^6.0.1 version: 6.0.1 @@ -61,14 +64,18 @@ importers: specifier: ^8.3.0 version: 8.5.1(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) typescript: - specifier: ^5.7.0 + specifier: ^5.9.0 version: 5.9.3 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@25.5.0) + specifier: ^3.2.0 + version: 3.2.4(@types/node@25.5.0) packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@andrewbranch/untar.js@1.0.3': resolution: {integrity: sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==} @@ -81,55 +88,80 @@ packages: resolution: {integrity: sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg==} engines: {node: '>=20'} - '@biomejs/biome@1.9.4': - resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@biomejs/biome@2.4.10': + resolution: {integrity: sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.9.4': - resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} + '@biomejs/cli-darwin-arm64@2.4.10': + resolution: {integrity: sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.9.4': - resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} + '@biomejs/cli-darwin-x64@2.4.10': + resolution: {integrity: sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.9.4': - resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} + '@biomejs/cli-linux-arm64-musl@2.4.10': + resolution: {integrity: sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [musl] - '@biomejs/cli-linux-arm64@1.9.4': - resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} + '@biomejs/cli-linux-arm64@2.4.10': + resolution: {integrity: sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [glibc] - '@biomejs/cli-linux-x64-musl@1.9.4': - resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} + '@biomejs/cli-linux-x64-musl@2.4.10': + resolution: {integrity: sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [musl] - '@biomejs/cli-linux-x64@1.9.4': - resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} + '@biomejs/cli-linux-x64@2.4.10': + resolution: {integrity: sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [glibc] - '@biomejs/cli-win32-arm64@1.9.4': - resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} + '@biomejs/cli-win32-arm64@2.4.10': + resolution: {integrity: sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.9.4': - resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} + '@biomejs/cli-win32-x64@2.4.10': + resolution: {integrity: sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -450,6 +482,14 @@ packages: peerDependencies: hono: ^4 + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -561,48 +601,56 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-arm64-musl@0.120.0': resolution: {integrity: sha512-gmMQ70gsPdDBgpcErvJEoWNBr7bJooSLlvOBVBSGfOzlP5NvJ3bFvnUeZZ9d+dPrqSngtonf7nyzWUTUj/U+lw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-ppc64-gnu@0.120.0': resolution: {integrity: sha512-T/kZuU0ajop0xhzVMwH5r3srC9Nqup5HaIo+3uFjIN5uPxa0LvSxC1ZqP4aQGJVW5G0z8/nCkjIfSMS91P/wzw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-gnu@0.120.0': resolution: {integrity: sha512-vn21KXLAXzaI3N5CZWlBr1iWeXLl9QFIMor7S1hUjUGTeUuWCoE6JZB040/ZNDwf+JXPX8Ao9KbmJq9FMC2iGw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-musl@0.120.0': resolution: {integrity: sha512-SUbUxlar007LTGmSLGIC5x/WJvwhdX+PwNzFJ9f/nOzZOrCFbOT4ikt7pJIRg1tXVsEfzk5mWpGO1NFiSs4PIw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-s390x-gnu@0.120.0': resolution: {integrity: sha512-hYiPJTxyfJY2+lMBFk3p2bo0R9GN+TtpPFlRqVchL1qvLG+pznstramHNvJlw9AjaoRUHwp9IKR7UZQnRPGjgQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-gnu@0.120.0': resolution: {integrity: sha512-q+5jSVZkprJCIy3dzJpApat0InJaoxQLsJuD6DkX8hrUS61z2lHQ1Fe9L2+TYbKHXCLWbL0zXe7ovkIdopBGMQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-musl@0.120.0': resolution: {integrity: sha512-D9QDDZNnH24e7X4ftSa6ar/2hCavETfW3uk0zgcMIrZNy459O5deTbWrjGzZiVrSWigGtlQwzs2McBP0QsfV1w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-parser/binding-openharmony-arm64@0.120.0': resolution: {integrity: sha512-TBU8ZwOUWAOUWVfmI16CYWbvh4uQb9zHnGBHsw5Cp2JUVG044OIY1CSHODLifqzQIMTXvDvLzcL89GGdUIqNrA==} @@ -675,41 +723,49 @@ packages: resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-arm64-musl@11.19.1': resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-x64-gnu@11.19.1': resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-x64-musl@11.19.1': resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} cpu: [x64] os: [linux] + libc: [musl] '@oxc-resolver/binding-openharmony-arm64@11.19.1': resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} @@ -736,6 +792,10 @@ packages: cpu: [x64] os: [win32] + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@publint/pack@0.1.4': resolution: {integrity: sha512-HDVTWq3H0uTXiU0eeSQntcVUTPP3GamzeXI41+x7uU9J65JgWQh3qWZHblR1i0npXfFtF+mxBiU2nJH8znxWnQ==} engines: {node: '>=18'} @@ -774,66 +834,79 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} @@ -872,6 +945,12 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -890,34 +969,43 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@vitest/expect@2.1.9': - resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + '@vitest/coverage-v8@3.2.4': + resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} + peerDependencies: + '@vitest/browser': 3.2.4 + vitest: 3.2.4 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - '@vitest/mocker@2.1.9': - resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@2.1.9': - resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - '@vitest/runner@2.1.9': - resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} - '@vitest/snapshot@2.1.9': - resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} - '@vitest/spy@2.1.9': - resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - '@vitest/utils@2.1.9': - resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} @@ -963,6 +1051,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -970,13 +1062,30 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-v8-to-istanbul@0.3.12: + resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} + brace-expansion@2.0.3: + resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -1117,12 +1226,18 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + emojilib@2.4.0: resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} @@ -1242,6 +1357,10 @@ packages: fix-dts-default-cjs-exports@1.0.1: resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} @@ -1293,6 +1412,11 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1320,6 +1444,9 @@ packages: resolution: {integrity: sha512-VJCEvtrezO1IAR+kqEYnxUOoStaQPGrCmX3j4wDTNOcD1uRPFpGlwQUIW8niPuvHXaTUxeOUl5MMDGrl+tmO9A==} engines: {node: '>=16.9.0'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -1364,6 +1491,25 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -1375,6 +1521,12 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -1400,6 +1552,9 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.7: resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} engines: {node: 20 || >=22} @@ -1407,6 +1562,13 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + marked-terminal@7.3.0: resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==} engines: {node: '>=16.0.0'} @@ -1454,9 +1616,21 @@ packages: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + mlly@1.8.1: resolution: {integrity: sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==} @@ -1543,6 +1717,9 @@ packages: oxc-resolver@11.19.1: resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} @@ -1563,12 +1740,13 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@8.3.0: resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -1729,6 +1907,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + skin-tone@2.0.0: resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} engines: {node: '>=8'} @@ -1759,14 +1941,25 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-json-comments@5.0.3: resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} engines: {node: '>=14.16'} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + sucrase@3.35.1: resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1780,6 +1973,10 @@ packages: resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} engines: {node: '>=14.18'} + test-exclude@7.0.2: + resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} + engines: {node: '>=18'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -1801,12 +1998,12 @@ packages: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} to-regex-range@5.0.1: @@ -1900,9 +2097,9 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite-node@2.1.9: - resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} - engines: {node: ^18.0.0 || >=20.0.0} + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true vite@5.4.21: @@ -1936,20 +2133,23 @@ packages: terser: optional: true - vitest@2.1.9: - resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.9 - '@vitest/ui': 2.1.9 + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 happy-dom: '*' jsdom: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@types/debug': + optional: true '@types/node': optional: true '@vitest/browser': @@ -1989,6 +2189,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -2034,6 +2238,11 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@andrewbranch/untar.js@1.0.3': {} '@arethetypeswrong/cli@0.18.2': @@ -2057,39 +2266,54 @@ snapshots: typescript: 5.6.1-rc validate-npm-package-name: 5.0.1 - '@biomejs/biome@1.9.4': + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bcoe/v8-coverage@1.0.2': {} + + '@biomejs/biome@2.4.10': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.9.4 - '@biomejs/cli-darwin-x64': 1.9.4 - '@biomejs/cli-linux-arm64': 1.9.4 - '@biomejs/cli-linux-arm64-musl': 1.9.4 - '@biomejs/cli-linux-x64': 1.9.4 - '@biomejs/cli-linux-x64-musl': 1.9.4 - '@biomejs/cli-win32-arm64': 1.9.4 - '@biomejs/cli-win32-x64': 1.9.4 + '@biomejs/cli-darwin-arm64': 2.4.10 + '@biomejs/cli-darwin-x64': 2.4.10 + '@biomejs/cli-linux-arm64': 2.4.10 + '@biomejs/cli-linux-arm64-musl': 2.4.10 + '@biomejs/cli-linux-x64': 2.4.10 + '@biomejs/cli-linux-x64-musl': 2.4.10 + '@biomejs/cli-win32-arm64': 2.4.10 + '@biomejs/cli-win32-x64': 2.4.10 - '@biomejs/cli-darwin-arm64@1.9.4': + '@biomejs/cli-darwin-arm64@2.4.10': optional: true - '@biomejs/cli-darwin-x64@1.9.4': + '@biomejs/cli-darwin-x64@2.4.10': optional: true - '@biomejs/cli-linux-arm64-musl@1.9.4': + '@biomejs/cli-linux-arm64-musl@2.4.10': optional: true - '@biomejs/cli-linux-arm64@1.9.4': + '@biomejs/cli-linux-arm64@2.4.10': optional: true - '@biomejs/cli-linux-x64-musl@1.9.4': + '@biomejs/cli-linux-x64-musl@2.4.10': optional: true - '@biomejs/cli-linux-x64@1.9.4': + '@biomejs/cli-linux-x64@2.4.10': optional: true - '@biomejs/cli-win32-arm64@1.9.4': + '@biomejs/cli-win32-arm64@2.4.10': optional: true - '@biomejs/cli-win32-x64@1.9.4': + '@biomejs/cli-win32-x64@2.4.10': optional: true '@braidai/lang@1.1.2': {} @@ -2265,6 +2489,17 @@ snapshots: hono: 4.12.8 optional: true + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/schema@0.1.3': {} + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2502,6 +2737,9 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.19.1': optional: true + '@pkgjs/parseargs@0.11.0': + optional: true + '@publint/pack@0.1.4': {} '@rollup/rollup-android-arm-eabi@4.59.0': @@ -2586,6 +2824,13 @@ snapshots: tslib: 2.8.1 optional: true + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.8': {} '@types/node-fetch@2.6.13': @@ -2609,45 +2854,66 @@ snapshots: dependencies: '@types/node': 22.19.15 - '@vitest/expect@2.1.9': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@25.5.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + ast-v8-to-istanbul: 0.3.12 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 2.0.0 + vitest: 3.2.4(@types/node@25.5.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.2.4': dependencies: - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.3.3 - tinyrainbow: 1.2.0 + tinyrainbow: 2.0.0 - '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@25.5.0))': + '@vitest/mocker@3.2.4(vite@5.4.21(@types/node@25.5.0))': dependencies: - '@vitest/spy': 2.1.9 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 5.4.21(@types/node@25.5.0) - '@vitest/pretty-format@2.1.9': + '@vitest/pretty-format@3.2.4': dependencies: - tinyrainbow: 1.2.0 + tinyrainbow: 2.0.0 - '@vitest/runner@2.1.9': + '@vitest/runner@3.2.4': dependencies: - '@vitest/utils': 2.1.9 - pathe: 1.1.2 + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 - '@vitest/snapshot@2.1.9': + '@vitest/snapshot@3.2.4': dependencies: - '@vitest/pretty-format': 2.1.9 + '@vitest/pretty-format': 3.2.4 magic-string: 0.30.21 - pathe: 1.1.2 + pathe: 2.0.3 - '@vitest/spy@2.1.9': + '@vitest/spy@3.2.4': dependencies: - tinyspy: 3.0.2 + tinyspy: 4.0.4 - '@vitest/utils@2.1.9': + '@vitest/utils@3.2.4': dependencies: - '@vitest/pretty-format': 2.1.9 + '@vitest/pretty-format': 3.2.4 loupe: 3.2.1 - tinyrainbow: 1.2.0 + tinyrainbow: 2.0.0 abort-controller@3.0.0: dependencies: @@ -2690,12 +2956,24 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.3: {} + any-promise@1.3.0: {} assertion-error@2.0.1: {} + ast-v8-to-istanbul@0.3.12: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + asynckit@0.4.0: {} + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -2711,6 +2989,14 @@ snapshots: - supports-color optional: true + brace-expansion@2.0.3: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -2823,7 +3109,6 @@ snapshots: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - optional: true debug@4.4.3: dependencies: @@ -2842,11 +3127,15 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + ee-first@1.1.1: optional: true emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + emojilib@2.4.0: {} encodeurl@2.0.0: @@ -3040,6 +3329,11 @@ snapshots: mlly: 1.8.1 rollup: 4.59.0 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data-encoder@1.7.2: {} form-data@4.0.5: @@ -3098,6 +3392,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + gopd@1.2.0: {} has-flag@4.0.0: {} @@ -3117,6 +3420,8 @@ snapshots: hono@4.12.8: optional: true + html-escaper@2.0.2: {} + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -3157,8 +3462,34 @@ snapshots: is-promise@4.0.0: optional: true - isexe@2.0.0: - optional: true + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 jiti@2.6.1: {} @@ -3167,6 +3498,10 @@ snapshots: joycon@3.1.1: {} + js-tokens@10.0.0: {} + + js-tokens@9.0.1: {} + json-schema-traverse@1.0.0: optional: true @@ -3199,12 +3534,24 @@ snapshots: loupe@3.2.1: {} + lru-cache@10.4.3: {} + lru-cache@11.2.7: {} magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.3.5: + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.4 + marked-terminal@7.3.0(marked@9.1.6): dependencies: ansi-escapes: 7.3.0 @@ -3247,8 +3594,18 @@ snapshots: mime-db: 1.54.0 optional: true + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.5 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.3 + minimist@1.2.8: {} + minipass@7.1.3: {} + mlly@1.8.1: dependencies: acorn: 8.16.0 @@ -3367,6 +3724,8 @@ snapshots: '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 + package-json-from-dist@1.0.1: {} + package-manager-detector@1.6.0: {} parse5-htmlparser2-tree-adapter@6.0.1: @@ -3380,14 +3739,16 @@ snapshots: parseurl@1.3.3: optional: true - path-key@3.1.1: - optional: true + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 path-to-regexp@8.3.0: optional: true - pathe@1.1.2: {} - pathe@2.0.3: {} pathval@2.0.1: {} @@ -3556,10 +3917,8 @@ snapshots: shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - optional: true - shebang-regex@3.0.0: - optional: true + shebang-regex@3.0.0: {} side-channel-list@1.0.0: dependencies: @@ -3595,6 +3954,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@4.1.0: {} + skin-tone@2.0.0: dependencies: unicode-emoji-modifier-base: 1.0.0 @@ -3618,12 +3979,26 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + strip-json-comments@5.0.3: {} + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + sucrase@3.35.1: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -3643,6 +4018,12 @@ snapshots: has-flag: 4.0.0 supports-color: 7.2.0 + test-exclude@7.0.2: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.5.0 + minimatch: 10.2.4 + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -3662,9 +4043,9 @@ snapshots: tinypool@1.1.1: {} - tinyrainbow@1.2.0: {} + tinyrainbow@2.0.0: {} - tinyspy@3.0.2: {} + tinyspy@4.0.4: {} to-regex-range@5.0.1: dependencies: @@ -3748,12 +4129,12 @@ snapshots: vary@1.1.2: optional: true - vite-node@2.1.9(@types/node@25.5.0): + vite-node@3.2.4(@types/node@25.5.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 - pathe: 1.1.2 + pathe: 2.0.3 vite: 5.4.21(@types/node@25.5.0) transitivePeerDependencies: - '@types/node' @@ -3775,27 +4156,30 @@ snapshots: '@types/node': 25.5.0 fsevents: 2.3.3 - vitest@2.1.9(@types/node@25.5.0): + vitest@3.2.4(@types/node@25.5.0): dependencies: - '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@25.5.0)) - '@vitest/pretty-format': 2.1.9 - '@vitest/runner': 2.1.9 - '@vitest/snapshot': 2.1.9 - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@5.4.21(@types/node@25.5.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.3.3 debug: 4.4.3 expect-type: 1.3.0 magic-string: 0.30.21 - pathe: 1.1.2 + pathe: 2.0.3 + picomatch: 4.0.3 std-env: 3.10.0 tinybench: 2.9.0 tinyexec: 0.3.2 + tinyglobby: 0.2.15 tinypool: 1.1.1 - tinyrainbow: 1.2.0 + tinyrainbow: 2.0.0 vite: 5.4.21(@types/node@25.5.0) - vite-node: 2.1.9(@types/node@25.5.0) + vite-node: 3.2.4(@types/node@25.5.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.5.0 @@ -3824,7 +4208,6 @@ snapshots: which@2.0.2: dependencies: isexe: 2.0.0 - optional: true why-is-node-running@2.3.0: dependencies: @@ -3837,6 +4220,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + wrappy@1.0.2: optional: true diff --git a/tsconfig.base.json b/tsconfig.base.json index 88bfee9..36cc48d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "ES2022", - "module": "ES2022", - "moduleResolution": "bundler", + "module": "nodenext", + "moduleResolution": "nodenext", "lib": ["ES2022"], "strict": true, "esModuleInterop": true,