diff --git a/README.md b/README.md index 11d4066..7fdf860 100644 --- a/README.md +++ b/README.md @@ -1,175 +1,22 @@ # @git-stunts/empty-graph +> **A graph database built on Git Object Storage.** + [![CI](https://github.com/git-stunts/empty-graph/actions/workflows/ci.yml/badge.svg)](https://github.com/git-stunts/empty-graph/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![npm version](https://badge.fury.io/js/%40git-stunts%2Fempty-graph.svg)](https://www.npmjs.com/package/@git-stunts/empty-graph) - -> *A **graph database that lives inside Git**. Stores data invisibly (no files) within Git commits using the **empty-tree pattern***. - -## Key highlights: - -- **Hexagonal architecture** with ports/adapters and DDD patterns -- **Roaring Bitmap indexes for O(1) parent/child lookups** -- Graph traversal algorithms (BFS, DFS, Dijkstra, A*, bidirectional) -- **Streaming-first design for handling millions of nodes** -- TypeScript definitions included - -Example included; benchmarks ready to fire up as soon as you finish cloning the git repo. - -## Use Cases - -EmptyGraph excels at specific scenarios where Git's properties align with your requirements. Here are concrete examples of what you can build: - -### Event Sourcing Systems - -Store domain events as commits, traverse history to replay state. Each event is immutable, cryptographically verified, and automatically timestamped. Build CQRS systems where the event store is a Git repository you can clone, branch, and inspect with standard tools. - -```javascript -// Each order event becomes a graph node -const orderCreated = await graph.createNode({ message: JSON.stringify({ type: 'OrderCreated', orderId: '123', items: [...] }) }); -const paymentReceived = await graph.createNode({ message: JSON.stringify({ type: 'PaymentReceived', orderId: '123', amount: 99.99 }), parents: [orderCreated] }); -``` - -### Knowledge Graphs & Semantic Networks - -Build interconnected knowledge bases where concepts link to related concepts. Perfect for documentation systems, wiki graphs, or AI training data that needs version control. Use `shortestPath()` to find connections between concepts. - -### Configuration & Dependency Graphs - -Track infrastructure-as-code dependencies, module relationships, or build graphs. Combine with GitOps workflows - your dependency graph lives in the same Git ecosystem as your infrastructure definitions. - -### Audit Trail Systems - -Every mutation is a commit with author, timestamp, and cryptographic proof. Use `git log` as your audit log, `git blame` to trace when data changed, and `git bisect` to find when relationships broke. Compliance-friendly by design. - -### Blockchain-like Data Structures - -Create immutable, content-addressed data structures with cryptographic verification. Each node's SHA proves its integrity and ancestry. Fork the graph, create branches, merge carefully - Git's distributed model handles replication. - -### Offline-First Applications - -Build apps that work without network connectivity. Clone the graph, query locally, sync when you reconnect. Perfect for field work, edge computing, or mobile apps that need local-first data with eventual consistency. - -### Distributed Databases - -Leverage Git's battle-tested sync and merge capabilities. Push to multiple remotes, fork repositories, handle conflicts with standard Git tooling. Your graph database inherits Git's distributed nature without additional infrastructure. - -## Why EmptyGraph? - -Git is usually used to track files. `EmptyGraph` subverts this by using Git's Directed Acyclic Graph (DAG) to store structured data *in the commits themselves*. - -Because all commits point to the "Empty Tree" (`4b825dc642cb6eb9a060e54bf8d69288fbee4904`), your data does not exist as files in the working directory—it exists entirely within the Git object database. - -> [!warning] -> **Reality Check**: When To Use This (And When **NOT** To) - -Let's pump the brakes... Just because you *can* store a graph in Git doesn't mean you *should*. Here's an honest assessment. - -### When EmptyGraph Makes Sense - -#### You need offline-first graph data. - -Git works without a network. Clone the repo, query locally, sync when you reconnect. Perfect for edge computing, field work, or airplane mode. - -#### You want Git-native replication. - -Your graph automatically inherits Git's distributed model. Fork it. Push to multiple remotes. Merge branches of graph data (carefully). No separate replication infrastructure. - -#### Your graph is append-mostly. - -Git loves immutable data. Add nodes, add edges, never delete? Perfect fit. *The reflog even lets you recover "deleted" nodes.* - -#### You're already in a Git ecosystem. - -If your workflow is Git-centric (CI/CD, GitOps, infrastructure-as-code), adding a graph that lives in Git means one less system to manage. - -#### You need an audit trail for free. - -Every mutation is a commit. `git log` is your audit log. `git blame` tells you when a node was added. `git bisect` can find when a relationship broke. - -#### The graph is small-to-medium (< 10M nodes). - -The bitmap index handles millions of nodes comfortably. At 1M nodes, you're looking at ~150-200MB of index data. That's fine. - -#### You value simplicity over features. - -No query language to learn. No cluster to manage. No connection pools. It's just JavaScript and Git. - -### When EmptyGraph Is A Bad Idea - -You should probably consider a more legit and powerful solution if: - -#### You need ACID transactions. - -Git commits are atomic, but there's no rollback, no isolation levels, no multi-statement transactions. If you need "transfer money from A to B" semantics, *please* use a real database. - -#### You need real-time updates. - -Git has no pubsub. No change streams. No WebSocket notifications. Polling `git fetch` is your only option, and it's not fast. -#### You need complex queries. +EmptyGraph leverages Git's internal Merkle DAG to store immutable, structured data without creating files in the working directory. It implements a secondary Roaring Bitmap index to enable high-performance O(1) graph traversal. -"Find all users who bought product X and also reviewed product Y in the last 30 days" - this requires a query planner, indexes, and probably Cypher or Gremlin. EmptyGraph gives you raw traversal primitives, not a query language (... *yet*). +## Documentation -#### Your graph is write-heavy. +**[Read the Full Documentation](https://empty-graph.git-stunts.io)** -Every write is a `git commit-tree` + `git commit`. That's fast, but not "10,000 writes per second" fast. Write-heavy workloads need a database that is designed for writes. - -#### You need to delete data (for real). - -GDPR "right to be forgotten"? Git's immutability works against you. Yes, you can rewrite history with `git filter-branch`, but it's painful and breaks every clone. - -#### The graph is huge (> 100M nodes). - -At some point, you're fighting Git's assumptions. Pack files get unwieldy. Index shards multiply. Clone times become brutal. Neo4j, DGraph, or TigerGraph exist for a reason. - -#### You need fine-grained access control. - -Git repos are all-or-nothing. Either you can clone it or you can't. There's no "user A can see nodes 1-100 but not 101-200." If you need row-level security, look elsewhere. - -> [!note] -> There *is* a trick to accomplish this, and I'll post it in a blog post sometime. You can run a [git startgate](https://github.com/flyingrobots/git-stargate) that uses git receive hooks + encryption to achieve "distributed opaque data", but it's too hacky to include in this project and you might want to question why you want to have private data live in git in the first place. - -#### Your team doesn't know Git. - -This sounds obvious, but: if your team struggles with `git rebase`, they're going to have a bad time debugging why the graph index is corrupt after a force push. - -### The Honest Summary - -
-Click to expand: When to use EmptyGraph vs alternatives - -| Use Case | EmptyGraph? | Better Alternative | -| --------------------------- | ----------- | ------------------- | -| Offline-first app data | Yes | - | -| Configuration graph | Yes | - | -| Dependency tracking | Yes | - | -| Knowledge base / wiki graph | Yes | - | -| Social network (prototype) | Maybe | Neo4j at scale | -| Financial transactions | No | PostgreSQL | -| Real-time collaboration | No | Firebase, Supabase | -| Analytics / OLAP | No | ClickHouse, DuckDB | -| Massive scale (100M+ nodes) | No | TigerGraph, Neptune | - -
- -## EmptyGraph is a **stunt**, not a product. - -It's proof that Git's data model is more powerful than people realize. It's a legitimate tool for specific use cases. But it's not a replacement for purpose-built graph databases. - -Use it when Git's properties (content-addressing, distributed replication, offline operation, universal tooling) align with your needs. Don't use it just because it's clever. - -### Why It Matters - -Graph databases are a $3B market. They require dedicated infrastructure, specialized query languages, careful capacity planning. - -EmptyGraph says: "What if the graph database was just... Git?" - -You already have Git. Your CI knows Git. Your backups cover Git. Your team understands Git (mostly). Now that same Git repository can store arbitrary graph data with O(1) edge lookups and full traversal capabilities. - -The traversal algorithms aren't novel. BFS is BFS. Kahn's algorithm is 62 years old. What's novel is *where they're running*: on top of a persistence layer that's simultaneously a version control system, a content-addressed store, and the most battle-tested distributed database in existence. +## Features -That's the stunt. Take something everyone has, use it for something no one intended, and make it work better than it has any right to. +- **Invisible Storage:** Uses the "Empty Tree" pattern to store data in `.git/objects`. +- **High Performance:** O(1) bidirectional lookups via sharded bitmap indexing. +- **Streaming:** Process millions of nodes with constant memory using async generators. +- **Algorithms:** Built-in BFS, DFS, Dijkstra, A*, and Bidirectional A* search. ## Installation @@ -183,886 +30,23 @@ npm install @git-stunts/empty-graph @git-stunts/plumbing import GitPlumbing from '@git-stunts/plumbing'; import EmptyGraph, { GitGraphAdapter } from '@git-stunts/empty-graph'; -// Create the persistence adapter -const plumbing = new GitPlumbing({ cwd: './my-db' }); +// Initialize on the current directory +const plumbing = new GitPlumbing({ cwd: '.' }); const persistence = new GitGraphAdapter({ plumbing }); - -// Create the graph with injected adapter const graph = new EmptyGraph({ persistence }); -// Create a node (commit) -const parentSha = await graph.createNode({ message: 'First Entry' }); - -// Create a child node -const childSha = await graph.createNode({ - message: 'Second Entry', - parents: [parentSha] -}); - -// Read data -const message = await graph.readNode(childSha); - -// List linear history (small graphs) -const nodes = await graph.listNodes({ ref: childSha, limit: 50 }); - -// Stream large graphs (millions of nodes) -for await (const node of graph.iterateNodes({ ref: childSha })) { - console.log(node.message); -} -``` - -## Interactive Demo - -Try EmptyGraph hands-on with our Docker-based interactive demo. It creates a sample e-commerce event graph and demonstrates traversal, event sourcing projections, and path finding. - -```bash -# Prerequisites: Docker must be running - -# 1. Set up the demo (creates container with sample events) -npm run demo:setup - -# 2. Run the interactive explorer -npm run demo:explore - -# 3. (Optional) Drop into the container shell for manual exploration -npm run demo - -# 4. Inspect the bitmap index structure -npm run demo:inspect - -# 5. Run Lagrangian pathfinding demo (resource-aware traversal) -npm run demo:lagrangian - -# 6. Run benchmarks -npm run demo:bench-streaming # Memory profile for 100K+ nodes -npm run demo:bench-traversal # Dijkstra/A*/BiA* performance at scale - -# 7. Clean up when done -npm run demo:down -``` - -> [!note] -> The demo is **idempotent** - running `demo:setup` multiple times will clean up and recreate the data. - -**What the demo shows:** - -- **Event Replay**: Reconstructs the full event history using `graph.traversal.ancestors()` -- **Event Sourcing**: Projects events into application state (users, carts, orders) -- **Branch Comparison**: Compares main branch vs cancelled-order branch -- **Path Finding**: Uses `graph.traversal.shortestPath()` to find paths between events -- **Topological Sort**: Shows dependency order with `graph.traversal.topologicalSort()` -- **Performance Comparison**: Shows O(1) bitmap index lookups vs git log (with speedup factors) -- **Index Inspector**: Visualizes shard distribution with ASCII charts -- **Lagrangian Pathfinding**: Resource-aware traversal using Dijkstra and A* with weighted costs -- **Streaming Benchmark**: Verifies constant memory overhead when iterating 100K+ nodes -- **Traversal Benchmark**: Compares Dijkstra, A*, and Bidirectional A* at scale - -**Sample output:** - -```text -[0148a1e4] UserCreated - {"userId":"user-alice-001","email":"alice@example.com","name":"Alice"} - -[6771a15f] CartCreated - {"userId":"user-alice-001","cartId":"cart-001"} - -[20744421] ItemAddedToCart - {"cartId":"cart-001","sku":"WIDGET-001","qty":2,"price":29.99} -... - -Shortest path from first to last event: 7 hops -Path: 0148a1e4 → 6771a15f → 20744421 → 6025e6ca → d2abe22c → fb285001 → c96d4e65 → d0583514 -``` - -## Features - -- **Invisible Storage**: No files are created in the working directory -- **Atomic Operations**: Leverages Git's reference updates for ACID guarantees -- **DAG Native**: Inherits Git's parent-child relationship model -- **High Performance**: O(1) lookups via sharded Roaring Bitmap indexes -- **Streaming First**: Handle millions of nodes without OOM via async generators -- **Security Hardened**: All refs validated, command injection prevention built-in - -## API Reference - -### `EmptyGraph` - -#### `constructor({ persistence, clock?, healthCacheTtlMs? })` - -Creates a new EmptyGraph instance. - -**Parameters:** -- `persistence` (GitGraphAdapter): Adapter implementing `GraphPersistencePort` & `IndexStoragePort` -- `clock` (ClockPort, optional): Clock adapter for timing. Defaults to `PerformanceClockAdapter` -- `healthCacheTtlMs` (number, optional): Health check cache TTL in milliseconds. Defaults to `5000` - -#### `async createNode({ message, parents = [], sign = false })` - -Creates a new graph node as a Git commit. - -**Parameters:** -- `message` (string): The node's message/data -- `parents` (string[]): Array of parent commit SHAs -- `sign` (boolean): Whether to GPG-sign the commit - -**Returns:** `Promise` - SHA of the created commit - -**Example:** -```javascript +// Create a node (writes to .git/objects) const sha = await graph.createNode({ - message: 'Node data', - parents: ['abc123...', 'def456...'] -}); -``` - -#### `async createNodes(nodes)` - -Creates multiple nodes in a single batch operation. - -**Parameters:** -- `nodes` (array): Array of `{ message: string, parents?: string[] }` objects. Parents can use placeholder syntax: `$0`, `$1`, etc. to reference nodes created earlier in the same batch. - -**Returns:** `Promise` - Array of created SHAs in same order as input - -**Validation:** All nodes are validated before any are created (fail-fast). - -**Example:** -```javascript -// Create a chain -const [root, child, grandchild] = await graph.createNodes([ - { message: 'Root node' }, - { message: 'Child', parents: ['$0'] }, - { message: 'Grandchild', parents: ['$1'] }, -]); - -// Create a DAG with merge -const shas = await graph.createNodes([ - { message: 'Root' }, - { message: 'Branch A', parents: ['$0'] }, - { message: 'Branch B', parents: ['$0'] }, - { message: 'Merge', parents: ['$1', '$2'] }, -]); -``` - -#### `async readNode(sha)` - -Reads a node's message. - -**Parameters:** -- `sha` (string): Commit SHA to read - -**Returns:** `Promise` - The node's message - -**Example:** -```javascript -const message = await graph.readNode(childSha); -console.log(message); // "Second Entry" -``` - -#### `async getNode(sha)` - -Returns the full GraphNode with all metadata. - -**Parameters:** -- `sha` (string): Commit SHA to read - -**Returns:** `Promise` - Full node with sha, author, date, message, and parents - -**Example:** -```javascript -const node = await graph.getNode(childSha); -console.log(node.sha); // "abc123..." -console.log(node.author); // "Alice " -console.log(node.date); // "2026-01-29T12:00:00Z" -console.log(node.message); // "Second Entry" -console.log(node.parents); // ["def456..."] -``` - -#### `async hasNode(sha)` - -Checks if a node exists in the graph. - -**Parameters:** -- `sha` (string): Commit SHA to check - -**Returns:** `Promise` - True if the node exists - -**Example:** -```javascript -const exists = await graph.hasNode('abc123...'); -if (exists) { - const node = await graph.getNode('abc123...'); -} -``` - -#### `async countNodes(ref)` - -Counts nodes reachable from a ref without loading all node data into memory. - -**Parameters:** -- `ref` (string): Git ref to count from (HEAD, branch, SHA) - -**Returns:** `Promise` - Number of nodes reachable from the ref - -**Example:** -```javascript -const count = await graph.countNodes('HEAD'); -console.log(`Graph contains ${count} nodes`); -``` - -#### `async listNodes({ ref, limit = 50 })` - -Lists nodes in history (for small graphs). - -**Parameters:** -- `ref` (string): Git ref to start from (HEAD, branch, SHA) -- `limit` (number): Maximum nodes to return - -**Returns:** `Promise` - -**Validation:** -- `ref` must match: `/^[a-zA-Z0-9_/-]+(\^|\~|\.\.|\.)*$/` -- `ref` cannot start with `-` or `--` - -#### `async *iterateNodes({ ref, limit = 1000000 })` - -Async generator for streaming large graphs. - -**Parameters:** -- `ref` (string): Git ref to start from -- `limit` (number): Maximum nodes to yield - -**Yields:** `GraphNode` instances - -**Example:** -```javascript -// Process 10 million nodes without OOM -for await (const node of graph.iterateNodes({ ref: 'HEAD' })) { - // Process each node -} -``` - -#### `async rebuildIndex(ref, options?)` - -Rebuilds the bitmap index for fast O(1) parent/child lookups. - -**Parameters:** -- `ref` (string): Git ref to rebuild the index from -- `options.limit` (number, optional): Maximum nodes to index (default: 10,000,000) - -**Returns:** `Promise` - OID of the created index tree - -**Persistence:** Creates a Git tree containing sharded bitmap data (~3 files per active SHA prefix). - -**Memory:** O(N) where N is number of nodes. Approximately 150-200MB for 1M nodes. - -**Example:** -```javascript -const treeOid = await graph.rebuildIndex('HEAD'); -// Store treeOid for later use with loadIndex() - -// With custom limit -const limitedTreeOid = await graph.rebuildIndex('HEAD', { limit: 100000 }); -``` - -#### `async loadIndex(treeOid)` - -Loads a pre-built bitmap index for O(1) queries. - -**Parameters:** -- `treeOid` (string): OID of the index tree (from `rebuildIndex()`) - -**Returns:** `Promise` - -**Memory:** Lazy loading - shards are loaded on-demand. Initial overhead is minimal (~50KB). - -**Example:** -```javascript -const treeOid = await graph.rebuildIndex('HEAD'); -await graph.loadIndex(treeOid); -// Now getParents() and getChildren() are available -``` - -#### `async getParents(sha)` - -Gets parent SHAs for a node using the bitmap index. Requires `loadIndex()` to be called first. - -**Parameters:** -- `sha` (string): The node's SHA - -**Returns:** `Promise` - Array of parent SHAs - -**Throws:** `Error` if index is not loaded - -**Example:** -```javascript -await graph.loadIndex(indexOid); -const parents = await graph.getParents(childSha); -console.log(parents); // ['abc123...', 'def456...'] -``` - -#### `async getChildren(sha)` - -Gets child SHAs for a node using the bitmap index. Requires `loadIndex()` to be called first. - -**Parameters:** -- `sha` (string): The node's SHA - -**Returns:** `Promise` - Array of child SHAs - -**Throws:** `Error` if index is not loaded - -**Example:** -```javascript -await graph.loadIndex(indexOid); -const children = await graph.getChildren(parentSha); -console.log(children); // ['abc123...'] -``` - -### Graph Traversal - -The `graph.traversal` service provides graph traversal algorithms for exploring node relationships. Requires a loaded index (call `loadIndex()` first). - -#### `async *bfs({ start, maxDepth?, maxNodes?, direction? })` - -Breadth-first traversal from a starting node. - -**Example:** -```javascript -// BFS traversal -for await (const node of graph.traversal.bfs({ start: sha, maxDepth: 5 })) { - console.log(node.sha, node.depth, node.parent); -} -``` - -#### `async *dfs({ start, maxDepth?, maxNodes?, direction? })` - -Depth-first traversal from a starting node. - -**Example:** -```javascript -// DFS traversal -for await (const node of graph.traversal.dfs({ start: sha })) { - console.log(node.sha); -} -``` - -#### `async *ancestors({ sha, maxDepth?, maxNodes? })` - -Find all ancestors of a node (follows parent edges). - -**Example:** -```javascript -// Find all ancestors -for await (const node of graph.traversal.ancestors({ sha })) { - console.log(node.sha); -} -``` - -#### `async *descendants({ sha, maxDepth?, maxNodes? })` - -Find all descendants of a node (follows child edges). - -**Example:** -```javascript -// Find all descendants -for await (const node of graph.traversal.descendants({ sha })) { - console.log(node.sha); -} -``` - -#### `async findPath({ from, to, maxDepth?, maxNodes? })` - -Find any path between two nodes. - -**Returns:** `Promise<{ found: boolean, path: string[] }>` - -**Example:** -```javascript -// Find any path between nodes -const result = await graph.traversal.findPath({ from: a, to: b }); -if (result.found) console.log(result.path); // ['a', 'x', 'y', 'b'] -``` - -#### `async shortestPath({ from, to, maxDepth?, maxNodes? })` - -Find the shortest path between two nodes using bidirectional BFS (unweighted). - -**Returns:** `Promise<{ found: boolean, path: string[], length: number }>` - -**Example:** -```javascript -// Find shortest path (bidirectional BFS) -const shortest = await graph.traversal.shortestPath({ from: a, to: b }); -console.log(shortest.path, shortest.length); -``` - -#### `async weightedShortestPath({ from, to, weightProvider?, direction? })` - -Find the shortest path using Dijkstra's algorithm with custom edge weights. - -**Parameters:** -- `from` (string): Starting SHA -- `to` (string): Target SHA -- `weightProvider` (function, optional): `async (fromSha, toSha) => number`. Defaults to `() => 1` -- `direction` ('children' | 'parents', optional): Traversal direction. Defaults to `'children'` - -**Returns:** `Promise<{ path: string[], totalCost: number }>` - -**Example:** -```javascript -// Lagrangian pathfinding with resource-weighted edges -const { path, totalCost } = await graph.traversal.weightedShortestPath({ - from: startSha, - to: targetSha, - weightProvider: async (from, to) => { - const message = await graph.readNode(to); - const event = JSON.parse(message); - const cpu = event.payload?.metrics?.cpu ?? 1; - const mem = event.payload?.metrics?.mem ?? 1; - return cpu * 1.0 + mem * 1.5; // Lagrangian cost - } -}); -``` - -#### `async aStarSearch({ from, to, weightProvider?, heuristicProvider?, direction? })` - -Find the shortest path using A* algorithm with heuristic guidance. - -**Parameters:** -- `from` (string): Starting SHA -- `to` (string): Target SHA -- `weightProvider` (function, optional): `async (fromSha, toSha) => number`. Defaults to `() => 1` -- `heuristicProvider` (function, optional): `(sha, targetSha) => number`. Defaults to `() => 0` (becomes Dijkstra) -- `direction` ('children' | 'parents', optional): Traversal direction. Defaults to `'children'` - -**Returns:** `Promise<{ path: string[], totalCost: number, nodesExplored: number }>` - -**Example:** -```javascript -// A* with heuristic for faster pathfinding -const { path, totalCost, nodesExplored } = await graph.traversal.aStarSearch({ - from: startSha, - to: targetSha, - weightProvider: async (from, to) => getCost(to), - heuristicProvider: (sha, target) => estimateDistance(sha, target) -}); -console.log(`Explored ${nodesExplored} nodes`); -``` - -#### `async bidirectionalAStar({ from, to, weightProvider?, forwardHeuristic?, backwardHeuristic? })` - -Bidirectional A* search that meets in the middle from both ends. - -**Parameters:** -- `from` (string): Starting SHA -- `to` (string): Target SHA -- `weightProvider` (function, optional): `async (fromSha, toSha) => number` -- `forwardHeuristic` (function, optional): `(sha, targetSha) => number` for forward search -- `backwardHeuristic` (function, optional): `(sha, targetSha) => number` for backward search - -**Returns:** `Promise<{ path: string[], totalCost: number, nodesExplored: number }>` - -**Example:** -```javascript -// Bidirectional A* for large graphs -const result = await graph.traversal.bidirectionalAStar({ - from: startSha, - to: targetSha, - forwardHeuristic: (sha, target) => estimate(sha, target), - backwardHeuristic: (sha, target) => estimate(sha, target) -}); -``` - -#### `async isReachable({ from, to, maxDepth?, maxNodes? })` - -Check if one node can reach another. - -**Returns:** `Promise` - -**Example:** -```javascript -// Check reachability -const canReach = await graph.traversal.isReachable({ from: a, to: b }); -``` - -#### `async commonAncestors({ shas, maxDepth?, maxNodes? })` - -Find common ancestors of multiple nodes. - -**Returns:** `Promise` - Array of common ancestor SHAs - -**Example:** -```javascript -// Find common ancestors of multiple nodes -const common = await graph.traversal.commonAncestors({ shas: [a, b, c] }); -``` - -#### `async *topologicalSort({ start, maxDepth?, maxNodes? })` - -Topological sort starting from a node (dependencies before dependents). - -**Example:** -```javascript -// Topological sort -for await (const node of graph.traversal.topologicalSort({ start: sha })) { - console.log(node.sha); // Dependencies before dependents -} -``` - -### Cancellation Support - -Long-running operations can be cancelled using `AbortSignal`: - -```javascript -import EmptyGraph, { createTimeoutSignal, OperationAbortedError } from '@git-stunts/empty-graph'; - -// With manual AbortController -const controller = new AbortController(); -setTimeout(() => controller.abort(), 5000); // Cancel after 5s - -try { - for await (const node of graph.iterateNodes({ ref: 'HEAD', signal: controller.signal })) { - // Process nodes... - } -} catch (err) { - if (err instanceof OperationAbortedError) { - console.log('Operation cancelled'); - } -} - -// With timeout signal (auto-aborts after duration) -const treeOid = await graph.rebuildIndex('HEAD', { - signal: createTimeoutSignal(30000) // 30 second timeout -}); -``` - -#### Traversal Options - -| Option | Default | Description | -| -------- | --------- | ------------- | -| `maxNodes` | 100000 | Maximum number of nodes to visit | -| `maxDepth` | 1000 | Maximum traversal depth | -| `direction` | `'forward'` | Traversal direction: `'forward'` or `'reverse'` for `bfs`/`dfs`; `'children'` or `'parents'` for weighted algorithms (`weightedShortestPath`, `aStarSearch`). | - -All traversal generators are async and memory-efficient, suitable for large graphs with millions of nodes. - -#### `hasIndex` - -Property that indicates whether an index is currently loaded. - -**Returns:** `boolean` - -**Example:** -```javascript -if (!graph.hasIndex) { - await graph.loadIndex(savedTreeOid); -} -``` - -#### `indexOid` - -Property that returns the current index tree OID. - -**Returns:** `string | null` - -#### `async saveIndex(ref?)` - -Saves the current index OID to a git ref for persistence across sessions. - -**Parameters:** -- `ref` (string, optional): The ref name (default: `'refs/empty-graph/index'`) - -**Returns:** `Promise` - -**Throws:** `Error` if no index has been built or loaded - -**Example:** -```javascript -await graph.rebuildIndex('HEAD'); -await graph.saveIndex(); // Persists to refs/empty-graph/index -``` - -#### `async loadIndexFromRef(ref?)` - -Loads the index from a previously saved git ref. - -**Parameters:** -- `ref` (string, optional): The ref name (default: `'refs/empty-graph/index'`) - -**Returns:** `Promise` - True if loaded, false if ref doesn't exist - -**Example:** -```javascript -// On application startup -const loaded = await graph.loadIndexFromRef(); -if (!loaded) { - await graph.rebuildIndex('HEAD'); - await graph.saveIndex(); -} -const parents = await graph.getParents(someSha); -``` - -#### `async getHealth()` - -Gets detailed health information for all components. - -**Returns:** `Promise` - Health status with component breakdown - -**HealthResult:** -- `status` ('healthy' | 'degraded' | 'unhealthy'): Overall health -- `components.repository`: Repository health with `status` and `latencyMs` -- `components.index`: Index health with `status`, `loaded`, and `shardCount` -- `cachedAt` (string, optional): ISO timestamp if result is cached - -Results are cached for the configured TTL (default: 5 seconds). - -**Example:** -```javascript -const health = await graph.getHealth(); -console.log(health.status); // 'healthy' | 'degraded' | 'unhealthy' -console.log(health.components.repository.latencyMs); // e.g., 1.23 -``` - -#### `async isReady()` - -K8s-style readiness probe: Can the service serve requests? - -**Returns:** `Promise` - True if all critical components are healthy - -Use this for Kubernetes readiness probes. A `false` result removes the pod from the load balancer. - -**Example:** -```javascript -// Express health endpoint -app.get('/ready', async (req, res) => { - const ready = await graph.isReady(); - res.status(ready ? 200 : 503).json({ ready }); + message: JSON.stringify({ type: 'UserCreated', name: 'Alice' }) }); -``` - -#### `async isAlive()` - -K8s-style liveness probe: Is the service running? - -**Returns:** `Promise` - True if the repository is accessible - -Use this for Kubernetes liveness probes. A `false` result typically triggers a container restart. - -**Example:** -```javascript -// Express health endpoint -app.get('/alive', async (req, res) => { - const alive = await graph.isAlive(); - res.status(alive ? 200 : 503).json({ alive }); -}); -``` - -### `GraphNode` - -Immutable entity representing a graph node. - -**Properties:** -- `sha` (string): Commit SHA -- `author` (string): Author name -- `date` (string): Commit date -- `message` (string): Node message/data -- `parents` (string[]): Array of parent SHAs - -## Working with the Bitmap Index - -The bitmap index enables O(1) parent/child lookups for large graphs. Here's the complete workflow: - -```javascript -import GitPlumbing from '@git-stunts/plumbing'; -import EmptyGraph, { GitGraphAdapter } from '@git-stunts/empty-graph'; - -// Setup -const plumbing = new GitPlumbing({ cwd: './my-graph-db' }); -const persistence = new GitGraphAdapter({ plumbing }); -const graph = new EmptyGraph({ persistence }); - -// === First-time setup: Build and persist the index === -const treeOid = await graph.rebuildIndex('HEAD'); -await graph.saveIndex(); // Persists to refs/empty-graph/index -console.log(`Index built: ${treeOid}`); - -// === Subsequent runs: Load the persisted index === -const loaded = await graph.loadIndexFromRef(); -if (!loaded) { - // Index doesn't exist yet, rebuild it - await graph.rebuildIndex('HEAD'); - await graph.saveIndex(); -} -// === Query parent/child relationships (O(1)) === -const parents = await graph.getParents(someSha); -const children = await graph.getChildren(someSha); +console.log(`Node created: ${sha}`); -console.log(`Node ${someSha} has:`); -console.log(` ${parents.length} parents:`, parents); -console.log(` ${children.length} children:`, children); +// Read it back +const data = await graph.readNode(sha); +console.log(data); ``` -**How it works internally:** - -1. `rebuildIndex()` walks the graph and builds sharded bitmap files: - - `meta_XX.json` - Maps SHAs to numeric IDs (sharded by SHA prefix) - - `shards_fwd_XX.json` - Forward edges (parent → children) - - `shards_rev_XX.json` - Reverse edges (child → parents) - -2. `loadIndex()` sets up lazy loading - shards are fetched on-demand: - ```javascript - // When you call getParents('abcd1234...') - // Only loads: meta_ab.json, shards_rev_ab.json - // Other shards remain unloaded until needed - ``` - -3. `saveIndex()` / `loadIndexFromRef()` persist the index tree OID to a git ref for reuse across sessions. - -## Choosing the Right Method - -| Scenario | Method | Reason | -| ---------- | -------- | -------- | -| < 1,000 nodes | `listNodes()` | Returns array, easier to work with | -| > 1,000 nodes | `iterateNodes()` | Streams results, constant memory | -| Single node lookup | `readNode()` | O(1) direct access | -| Find parents/children | `getParents()` / `getChildren()` | O(1) with bitmap index | - -```javascript -// Example: Processing small graphs -const recentNodes = await graph.listNodes({ ref: 'HEAD', limit: 100 }); -recentNodes.forEach(node => console.log(node.message)); - -// Example: Processing large graphs (memory-safe) -for await (const node of graph.iterateNodes({ ref: 'HEAD' })) { - await processNode(node); // Handle millions of nodes without OOM -} - -// Example: O(1) relationship queries with bitmap index -const treeOid = await graph.rebuildIndex('HEAD'); -await graph.loadIndex(treeOid); -const parents = await graph.getParents(someSha); -const children = await graph.getChildren(someSha); -``` - -## Performance Characteristics - -| Operation | Complexity | Notes | -|-----------|------------|-------| -| Create Node | O(1) | Constant time commit creation | -| Read Node | O(1) | Direct SHA lookup | -| List Nodes (small) | O(n) | Linear scan up to limit | -| Iterate Nodes (large) | O(n) | Streaming, constant memory | -| Bitmap Index Lookup | O(1) | With `BitmapIndexService` | - -## Architecture - -EmptyGraph follows hexagonal architecture (ports & adapters): - -```mermaid -flowchart TD - EG[EmptyGraph
(Facade)] - GS[GraphService
(Domain)] - IRS[IndexRebuildService
(Domain)] - GPP[GraphPersistencePort
(Port)] - ISP[IndexStoragePort
(Port)] - GGA[GitGraphAdapter
(Adapter)] - PL[@git-stunts/plumbing] - - EG --> GS - EG --> IRS - GS --> GPP - GS --> ISP - IRS --> ISP - GPP --> GGA - ISP --> GGA - GGA --> PL -``` - -**Key Components:** - -| Layer | Component | Responsibility | -| --- | --- | --- | -| Facade | `EmptyGraph` | Simplified public API | -| Domain | `GraphService` | Node CRUD operations | -| Domain | `IndexRebuildService` | Index building orchestration | -| Domain | `BitmapIndexBuilder` | Pure in-memory index construction | -| Domain | `BitmapIndexReader` | O(1) index queries | -| Domain | `HealthCheckService` | K8s-style health probes | -| Port | `GraphPersistencePort` | Graph storage contract | -| Port | `IndexStoragePort` | Index storage contract | -| Port | `ClockPort` | High-resolution timing abstraction | -| Adapter | `GitGraphAdapter` | Git implementation of both ports | -| Adapter | `PerformanceClockAdapter` | Node.js clock (uses `perf_hooks`) | -| Adapter | `GlobalClockAdapter` | Bun/Deno/Browser clock (uses global `performance`) | - -## Error Handling - -Common errors and solutions: - -### Invalid Ref Format -```javascript -// Error: Invalid ref format: --upload-pack -// Solution: Refs must be alphanumeric, /, -, _, ^, ~, or . -const nodes = await graph.listNodes({ ref: 'main' }); -``` - -### GraphNode Validation Error -```javascript -// Error: GraphNode requires a valid sha string -// Solution: Ensure createNode returned a valid SHA -const sha = await graph.createNode({ message: 'data' }); -const message = await graph.readNode(sha); -``` - -### Ref Too Long -```javascript -// Error: Ref too long: 2048 chars. Maximum is 1024 -// Solution: Use shorter branch names or commit SHAs -const nodes = await graph.listNodes({ ref: 'abc123def' }); // Use SHA instead -``` - -### Invalid OID Format -```javascript -// Error: Invalid OID format: not-a-valid-sha -// Solution: OIDs must be 4-64 hexadecimal characters -const message = await graph.readNode('abc123def456'); // Valid short SHA -``` - -## Security - -- **Ref Validation**: All refs validated against strict patterns to prevent injection -- **OID Validation**: All Git object IDs validated against `/^[0-9a-fA-F]{4,64}$/` -- **Length Limits**: Refs cannot exceed 1024 characters, OIDs cannot exceed 64 characters -- **No Arbitrary Commands**: Only whitelisted Git plumbing commands -- **Delimiter Safety**: Uses ASCII Record Separator (`\x1E`) to prevent message collision -- **Streaming Only**: No unbounded memory usage -- **UTF-8 Safe**: Streaming decoder handles multibyte characters across chunk boundaries - -See [SECURITY.md](./SECURITY.md) for details. - -## Development Setup - -### Git Hooks - -This project uses custom git hooks (no husky). To enable pre-commit linting: - -```bash -npm run setup:hooks -``` - -This configures git to use the hooks in `scripts/hooks/`. The pre-commit hook runs ESLint on staged JavaScript files. - -To bypass the hook temporarily (not recommended): -```bash -git commit --no-verify -``` - -## Contributing - -See [CONTRIBUTING.md](./CONTRIBUTING.md) for development guidelines. - ## License Apache-2.0 © James Ross diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js new file mode 100644 index 0000000..d4ddc5f --- /dev/null +++ b/docs/.vitepress/config.js @@ -0,0 +1,68 @@ +import { defineConfig } from 'vitepress' + +export default defineConfig({ + title: "EmptyGraph", + description: "A graph database that lives inside Git", + head: [ + ['meta', { property: 'og:image', content: '/images/empty-graph-social.jpg' }], + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], + ['meta', { name: 'twitter:image', content: '/images/empty-graph-social.jpg' }], + ], + themeConfig: { + logo: '/logo.png', + nav: [ + { text: 'Guide', link: '/guide/what-is-this' }, + { text: 'API', link: '/api/' }, + { text: 'Stunts', link: '/stunts/' }, + { text: 'GitHub', link: 'https://github.com/git-stunts/empty-graph' } + ], + sidebar: [ + { + text: 'The Guide', + items: [ + { text: 'What is this?', link: '/guide/what-is-this' }, + { text: 'Getting Started', link: '/guide/getting-started' }, + { text: 'Core Concepts', link: '/guide/core-concepts' }, + { text: 'Operations & Safety', link: '/guide/operations' }, + { text: 'Comparison', link: '/guide/comparison' }, + { text: 'Troubleshooting', link: '/guide/troubleshooting' }, + { text: 'Roadmap', link: '/guide/roadmap' }, + { text: 'Architecture', link: '/guide/architecture' }, + { text: 'Interactive Demo', link: '/guide/interactive-demo' }, + ] + }, + { + text: 'The Stunts', + items: [ + { text: 'Event Sourcing', link: '/stunts/event-sourcing' }, + { text: 'Resource-Aware Routing', link: '/stunts/lagrangian-routing' }, + { text: 'Infinite Memory Streaming', link: '/stunts/streaming' }, + { text: 'Invisible Metadata', link: '/stunts/invisible-storage' }, + ] + }, + { + text: 'API Reference', + items: [ + { text: 'EmptyGraph Facade', link: '/api/empty-graph' }, + { text: 'GraphService', link: '/api/graph-service' }, + { text: 'TraversalService', link: '/api/traversal-service' }, + { text: 'BitmapIndex', link: '/api/bitmap-index' }, + ] + }, + { + text: 'Internals', + items: [ + { text: 'The Bitmap Index', link: '/internals/bitmap-index' }, + { text: 'Binary Plumbing', link: '/internals/plumbing' }, + ] + } + ], + socialLinks: [ + { icon: 'github', link: 'https://github.com/git-stunts/empty-graph' } + ], + footer: { + message: 'Released under the Apache-2.0 License.', + copyright: 'Copyright © 2026-present James Ross' + } + } +}) diff --git a/docs/.vitepress/dist/404.html b/docs/.vitepress/dist/404.html new file mode 100644 index 0000000..f686f2e --- /dev/null +++ b/docs/.vitepress/dist/404.html @@ -0,0 +1,25 @@ + + + + + + 404 | EmptyGraph + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/api/bitmap-index.html b/docs/.vitepress/dist/api/bitmap-index.html new file mode 100644 index 0000000..fa5d027 --- /dev/null +++ b/docs/.vitepress/dist/api/bitmap-index.html @@ -0,0 +1,28 @@ + + + + + + EmptyGraph + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/api/empty-graph.html b/docs/.vitepress/dist/api/empty-graph.html new file mode 100644 index 0000000..078aab1 --- /dev/null +++ b/docs/.vitepress/dist/api/empty-graph.html @@ -0,0 +1,29 @@ + + + + + + EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

EmptyGraph

The main facade class that ties everything together.

javascript
import EmptyGraph from '@git-stunts/empty-graph';
+const graph = new EmptyGraph({ persistence });

Methods

createNode({ message, parents })

Creates a new node (commit).

readNode(sha)

Reads the message of a node.

rebuildIndex(ref)

Builds the bitmap index for O(1) lookups.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/api/graph-service.html b/docs/.vitepress/dist/api/graph-service.html new file mode 100644 index 0000000..2f050de --- /dev/null +++ b/docs/.vitepress/dist/api/graph-service.html @@ -0,0 +1,28 @@ + + + + + + EmptyGraph + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/api/index.html b/docs/.vitepress/dist/api/index.html new file mode 100644 index 0000000..08200fb --- /dev/null +++ b/docs/.vitepress/dist/api/index.html @@ -0,0 +1,28 @@ + + + + + + API Reference | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

API Reference

The primary entry point is the EmptyGraph class.

Core Classes

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/api/traversal-service.html b/docs/.vitepress/dist/api/traversal-service.html new file mode 100644 index 0000000..a435e87 --- /dev/null +++ b/docs/.vitepress/dist/api/traversal-service.html @@ -0,0 +1,28 @@ + + + + + + TraversalService | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

TraversalService

The engine for walking the graph.

Methods

bfs({ start, maxDepth })

Breadth-First Search generator.

shortestPath({ from, to })

Finds shortest path using Bidirectional BFS.

weightedShortestPath({ from, to, weightProvider })

Dijkstra's algorithm with custom weights (e.g., for Lagrangian routing).

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.js b/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.js new file mode 100644 index 0000000..067f2f0 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a}from"./chunks/framework.DvGhUH3j.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"api/bitmap-index.md","filePath":"api/bitmap-index.md"}'),i={name:"api/bitmap-index.md"};function n(p,r,o,s,c,d){return a(),t("div")}const f=e(i,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.lean.js b/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.lean.js new file mode 100644 index 0000000..067f2f0 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_bitmap-index.md.DsG7ME_t.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as a}from"./chunks/framework.DvGhUH3j.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"api/bitmap-index.md","filePath":"api/bitmap-index.md"}'),i={name:"api/bitmap-index.md"};function n(p,r,o,s,c,d){return a(),t("div")}const f=e(i,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.js b/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.js new file mode 100644 index 0000000..b88fe74 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ae as i}from"./chunks/framework.DvGhUH3j.js";const k=JSON.parse('{"title":"EmptyGraph","description":"","frontmatter":{},"headers":[],"relativePath":"api/empty-graph.md","filePath":"api/empty-graph.md"}'),r={name:"api/empty-graph.md"};function h(p,a,n,d,o,l){return t(),s("div",null,[...a[0]||(a[0]=[i('

EmptyGraph

The main facade class that ties everything together.

javascript
import EmptyGraph from '@git-stunts/empty-graph';\nconst graph = new EmptyGraph({ persistence });

Methods

createNode({ message, parents })

Creates a new node (commit).

readNode(sha)

Reads the message of a node.

rebuildIndex(ref)

Builds the bitmap index for O(1) lookups.

',10)])])}const m=e(r,[["render",h]]);export{k as __pageData,m as default}; diff --git a/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.lean.js b/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.lean.js new file mode 100644 index 0000000..4d27f61 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_empty-graph.md.m8YhdPmC.lean.js @@ -0,0 +1 @@ +import{_ as e,c as s,o as t,ae as i}from"./chunks/framework.DvGhUH3j.js";const k=JSON.parse('{"title":"EmptyGraph","description":"","frontmatter":{},"headers":[],"relativePath":"api/empty-graph.md","filePath":"api/empty-graph.md"}'),r={name:"api/empty-graph.md"};function h(p,a,n,d,o,l){return t(),s("div",null,[...a[0]||(a[0]=[i("",10)])])}const m=e(r,[["render",h]]);export{k as __pageData,m as default}; diff --git a/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.js b/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.js new file mode 100644 index 0000000..a40926f --- /dev/null +++ b/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"api/graph-service.md","filePath":"api/graph-service.md"}'),t={name:"api/graph-service.md"};function c(s,p,i,o,n,_){return r(),a("div")}const f=e(t,[["render",c]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.lean.js b/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.lean.js new file mode 100644 index 0000000..a40926f --- /dev/null +++ b/docs/.vitepress/dist/assets/api_graph-service.md.w4rOehRM.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as r}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"api/graph-service.md","filePath":"api/graph-service.md"}'),t={name:"api/graph-service.md"};function c(s,p,i,o,n,_){return r(),a("div")}const f=e(t,[["render",c]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.js b/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.js new file mode 100644 index 0000000..dab53e9 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.js @@ -0,0 +1 @@ +import{_ as a,c as r,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"API Reference","description":"","frontmatter":{},"headers":[],"relativePath":"api/index.md","filePath":"api/index.md"}'),s={name:"api/index.md"};function n(l,e,o,c,p,h){return i(),r("div",null,[...e[0]||(e[0]=[t('

API Reference

The primary entry point is the EmptyGraph class.

Core Classes

',4)])])}const f=a(s,[["render",n]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.lean.js b/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.lean.js new file mode 100644 index 0000000..d9d0445 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_index.md.seH7UXM8.lean.js @@ -0,0 +1 @@ +import{_ as a,c as r,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"API Reference","description":"","frontmatter":{},"headers":[],"relativePath":"api/index.md","filePath":"api/index.md"}'),s={name:"api/index.md"};function n(l,e,o,c,p,h){return i(),r("div",null,[...e[0]||(e[0]=[t("",4)])])}const f=a(s,[["render",n]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.js b/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.js new file mode 100644 index 0000000..940cd22 --- /dev/null +++ b/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as r,ae as o}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"TraversalService","description":"","frontmatter":{},"headers":[],"relativePath":"api/traversal-service.md","filePath":"api/traversal-service.md"}'),s={name:"api/traversal-service.md"};function h(i,e,d,c,l,n){return r(),a("div",null,[...e[0]||(e[0]=[o('

TraversalService

The engine for walking the graph.

Methods

bfs({ start, maxDepth })

Breadth-First Search generator.

shortestPath({ from, to })

Finds shortest path using Bidirectional BFS.

weightedShortestPath({ from, to, weightProvider })

Dijkstra's algorithm with custom weights (e.g., for Lagrangian routing).

',9)])])}const f=t(s,[["render",h]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.lean.js b/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.lean.js new file mode 100644 index 0000000..12c680f --- /dev/null +++ b/docs/.vitepress/dist/assets/api_traversal-service.md.B5EG-8W-.lean.js @@ -0,0 +1 @@ +import{_ as t,c as a,o as r,ae as o}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"TraversalService","description":"","frontmatter":{},"headers":[],"relativePath":"api/traversal-service.md","filePath":"api/traversal-service.md"}'),s={name:"api/traversal-service.md"};function h(i,e,d,c,l,n){return r(),a("div",null,[...e[0]||(e[0]=[o("",9)])])}const f=t(s,[["render",h]]);export{m as __pageData,f as default}; diff --git a/docs/.vitepress/dist/assets/app.3wzS_Eo3.js b/docs/.vitepress/dist/assets/app.3wzS_Eo3.js new file mode 100644 index 0000000..7bb2040 --- /dev/null +++ b/docs/.vitepress/dist/assets/app.3wzS_Eo3.js @@ -0,0 +1 @@ +import{t as p}from"./chunks/theme.Bte6VuTq.js";import{R as s,a0 as i,a1 as u,a2 as c,a3 as l,a4 as f,a5 as d,a6 as m,a7 as h,a8 as g,a9 as A,d as v,u as y,v as C,s as P,aa as b,ab as w,ac as R,ad as E}from"./chunks/framework.DvGhUH3j.js";function r(e){if(e.extends){const a=r(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const n=r(p),S=v({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=y();return C(()=>{P(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&b(),w(),R(),n.setup&&n.setup(),()=>E(n.Layout)}});async function T(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(u,e);const t=c(e.route);return a.provide(l,t),a.component("Content",f),a.component("ClientOnly",d),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),n.enhanceApp&&await n.enhanceApp({app:a,router:e,siteData:m}),{app:a,router:e,data:t}}function D(){return A(S)}function _(){let e=s;return h(a=>{let t=g(a),o=null;return t&&(e&&(t=t.replace(/\.js$/,".lean.js")),o=import(t)),s&&(e=!1),o},n.NotFound)}s&&T().then(({app:e,router:a,data:t})=>{a.go().then(()=>{i(a.route,t.site),e.mount("#app")})});export{T as createApp}; diff --git a/docs/.vitepress/dist/assets/chunks/framework.DvGhUH3j.js b/docs/.vitepress/dist/assets/chunks/framework.DvGhUH3j.js new file mode 100644 index 0000000..713b55f --- /dev/null +++ b/docs/.vitepress/dist/assets/chunks/framework.DvGhUH3j.js @@ -0,0 +1,19 @@ +/** +* @vue/shared v3.5.27 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Fs(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const re={},Ot=[],ke=()=>{},Yr=()=>!1,nn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Hs=e=>e.startsWith("onUpdate:"),fe=Object.assign,Ds=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Lo=Object.prototype.hasOwnProperty,Q=(e,t)=>Lo.call(e,t),B=Array.isArray,It=e=>Ln(e)==="[object Map]",Jr=e=>Ln(e)==="[object Set]",G=e=>typeof e=="function",le=e=>typeof e=="string",Ze=e=>typeof e=="symbol",te=e=>e!==null&&typeof e=="object",zr=e=>(te(e)||G(e))&&G(e.then)&&G(e.catch),Qr=Object.prototype.toString,Ln=e=>Qr.call(e),No=e=>Ln(e).slice(8,-1),Zr=e=>Ln(e)==="[object Object]",Nn=e=>le(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,mt=Fs(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Fn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Fo=/-\w/g,Le=Fn(e=>e.replace(Fo,t=>t.slice(1).toUpperCase())),Ho=/\B([A-Z])/g,at=Fn(e=>e.replace(Ho,"-$1").toLowerCase()),Hn=Fn(e=>e.charAt(0).toUpperCase()+e.slice(1)),_n=Fn(e=>e?`on${Hn(e)}`:""),ot=(e,t)=>!Object.is(e,t),Zn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},Do=e=>{const t=parseFloat(e);return isNaN(t)?e:t},$o=e=>{const t=le(e)?Number(e):NaN;return isNaN(t)?e:t};let rr;const Dn=()=>rr||(rr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function $s(e){if(B(e)){const t={};for(let n=0;n{if(n){const s=n.split(Vo);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function js(e){let t="";if(le(e))t=e;else if(B(e))for(let n=0;n!!(e&&e.__v_isRef===!0),Ko=e=>le(e)?e:e==null?"":B(e)||te(e)&&(e.toString===Qr||!G(e.toString))?ni(e)?Ko(e.value):JSON.stringify(e,si,2):String(e),si=(e,t)=>ni(t)?si(e,t.value):It(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[es(s,i)+" =>"]=r,n),{})}:Jr(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>es(n))}:Ze(t)?es(t):te(t)&&!B(t)&&!Zr(t)?String(t):t,es=(e,t="")=>{var n;return Ze(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.5.27 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let pe;class qo{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=pe,!t&&pe&&(this.index=(pe.scopes||(pe.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0&&--this._on===0&&(pe=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let n,s;for(n=0,s=this.effects.length;n0)return;if(Ut){let t=Ut;for(Ut=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;kt;){let t=kt;for(kt=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function ci(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function ai(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),ks(s),Xo(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function Ss(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(fi(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function fi(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Gt)||(e.globalVersion=Gt,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Ss(e))))return;e.flags|=2;const t=e.dep,n=se,s=Fe;se=e,Fe=!0;try{ci(e);const r=e.fn(e._value);(t.version===0||ot(r,e._value))&&(e.flags|=128,e._value=r,t.version++)}catch(r){throw t.version++,r}finally{se=n,Fe=s,ai(e),e.flags&=-3}}function ks(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)ks(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function Xo(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Fe=!0;const ui=[];function Xe(){ui.push(Fe),Fe=!1}function Ye(){const e=ui.pop();Fe=e===void 0?!0:e}function ir(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=se;se=void 0;try{t()}finally{se=n}}}let Gt=0;class Yo{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class $n{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!se||!Fe||se===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==se)n=this.activeLink=new Yo(se,this),se.deps?(n.prevDep=se.depsTail,se.depsTail.nextDep=n,se.depsTail=n):se.deps=se.depsTail=n,di(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=se.depsTail,n.nextDep=void 0,se.depsTail.nextDep=n,se.depsTail=n,se.deps===n&&(se.deps=s)}return n}trigger(t){this.version++,Gt++,this.notify(t)}notify(t){Vs();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Ws()}}}function di(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)di(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const Tn=new WeakMap,vt=Symbol(""),xs=Symbol(""),Xt=Symbol("");function me(e,t,n){if(Fe&&se){let s=Tn.get(e);s||Tn.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new $n),r.map=s,r.key=n),r.track()}}function Ge(e,t,n,s,r,i){const l=Tn.get(e);if(!l){Gt++;return}const o=c=>{c&&c.trigger()};if(Vs(),t==="clear")l.forEach(o);else{const c=B(e),u=c&&Nn(n);if(c&&n==="length"){const a=Number(s);l.forEach((h,v)=>{(v==="length"||v===Xt||!Ze(v)&&v>=a)&&o(h)})}else switch((n!==void 0||l.has(void 0))&&o(l.get(n)),u&&o(l.get(Xt)),t){case"add":c?u&&o(l.get("length")):(o(l.get(vt)),It(e)&&o(l.get(xs)));break;case"delete":c||(o(l.get(vt)),It(e)&&o(l.get(xs)));break;case"set":It(e)&&o(l.get(vt));break}}Ws()}function Jo(e,t){const n=Tn.get(e);return n&&n.get(t)}function At(e){const t=z(e);return t===e?t:(me(t,"iterate",Xt),Ae(e)?t:t.map(He))}function jn(e){return me(e=z(e),"iterate",Xt),e}function nt(e,t){return Je(e)?Ft(lt(e)?He(t):t):He(t)}const zo={__proto__:null,[Symbol.iterator](){return ns(this,Symbol.iterator,e=>nt(this,e))},concat(...e){return At(this).concat(...e.map(t=>B(t)?At(t):t))},entries(){return ns(this,"entries",e=>(e[1]=nt(this,e[1]),e))},every(e,t){return Ue(this,"every",e,t,void 0,arguments)},filter(e,t){return Ue(this,"filter",e,t,n=>n.map(s=>nt(this,s)),arguments)},find(e,t){return Ue(this,"find",e,t,n=>nt(this,n),arguments)},findIndex(e,t){return Ue(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Ue(this,"findLast",e,t,n=>nt(this,n),arguments)},findLastIndex(e,t){return Ue(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Ue(this,"forEach",e,t,void 0,arguments)},includes(...e){return ss(this,"includes",e)},indexOf(...e){return ss(this,"indexOf",e)},join(e){return At(this).join(e)},lastIndexOf(...e){return ss(this,"lastIndexOf",e)},map(e,t){return Ue(this,"map",e,t,void 0,arguments)},pop(){return jt(this,"pop")},push(...e){return jt(this,"push",e)},reduce(e,...t){return or(this,"reduce",e,t)},reduceRight(e,...t){return or(this,"reduceRight",e,t)},shift(){return jt(this,"shift")},some(e,t){return Ue(this,"some",e,t,void 0,arguments)},splice(...e){return jt(this,"splice",e)},toReversed(){return At(this).toReversed()},toSorted(e){return At(this).toSorted(e)},toSpliced(...e){return At(this).toSpliced(...e)},unshift(...e){return jt(this,"unshift",e)},values(){return ns(this,"values",e=>nt(this,e))}};function ns(e,t,n){const s=jn(e),r=s[t]();return s!==e&&!Ae(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.done||(i.value=n(i.value)),i}),r}const Qo=Array.prototype;function Ue(e,t,n,s,r,i){const l=jn(e),o=l!==e&&!Ae(e),c=l[t];if(c!==Qo[t]){const h=c.apply(e,i);return o?He(h):h}let u=n;l!==e&&(o?u=function(h,v){return n.call(this,nt(e,h),v,e)}:n.length>2&&(u=function(h,v){return n.call(this,h,v,e)}));const a=c.call(l,u,s);return o&&r?r(a):a}function or(e,t,n,s){const r=jn(e);let i=n;return r!==e&&(Ae(e)?n.length>3&&(i=function(l,o,c){return n.call(this,l,o,c,e)}):i=function(l,o,c){return n.call(this,l,nt(e,o),c,e)}),r[t](i,...s)}function ss(e,t,n){const s=z(e);me(s,"iterate",Xt);const r=s[t](...n);return(r===-1||r===!1)&&Vn(n[0])?(n[0]=z(n[0]),s[t](...n)):r}function jt(e,t,n=[]){Xe(),Vs();const s=z(e)[t].apply(e,n);return Ws(),Ye(),s}const Zo=Fs("__proto__,__v_isRef,__isVue"),hi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(Ze));function el(e){Ze(e)||(e=String(e));const t=z(this);return me(t,"has",e),t.hasOwnProperty(e)}class pi{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?fl:yi:i?vi:mi).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const l=B(t);if(!r){let c;if(l&&(c=zo[n]))return c;if(n==="hasOwnProperty")return el}const o=Reflect.get(t,n,ae(t)?t:s);if((Ze(n)?hi.has(n):Zo(n))||(r||me(t,"get",n),i))return o;if(ae(o)){const c=l&&Nn(n)?o:o.value;return r&&te(c)?Yt(c):c}return te(o)?r?Yt(o):Nt(o):o}}class gi extends pi{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];const l=B(t)&&Nn(n);if(!this._isShallow){const u=Je(i);if(!Ae(s)&&!Je(s)&&(i=z(i),s=z(s)),!l&&ae(i)&&!ae(s))return u||(i.value=s),!0}const o=l?Number(n)e,cn=e=>Reflect.getPrototypeOf(e);function il(e,t,n){return function(...s){const r=this.__v_raw,i=z(r),l=It(i),o=e==="entries"||e===Symbol.iterator&&l,c=e==="keys"&&l,u=r[e](...s),a=n?Ts:t?Ft:He;return!t&&me(i,"iterate",c?xs:vt),fe(Object.create(u),{next(){const{value:h,done:v}=u.next();return v?{value:h,done:v}:{value:o?[a(h[0]),a(h[1])]:a(h),done:v}}})}}function an(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ol(e,t){const n={get(r){const i=this.__v_raw,l=z(i),o=z(r);e||(ot(r,o)&&me(l,"get",r),me(l,"get",o));const{has:c}=cn(l),u=t?Ts:e?Ft:He;if(c.call(l,r))return u(i.get(r));if(c.call(l,o))return u(i.get(o));i!==l&&i.get(r)},get size(){const r=this.__v_raw;return!e&&me(z(r),"iterate",vt),r.size},has(r){const i=this.__v_raw,l=z(i),o=z(r);return e||(ot(r,o)&&me(l,"has",r),me(l,"has",o)),r===o?i.has(r):i.has(r)||i.has(o)},forEach(r,i){const l=this,o=l.__v_raw,c=z(o),u=t?Ts:e?Ft:He;return!e&&me(c,"iterate",vt),o.forEach((a,h)=>r.call(i,u(a),u(h),l))}};return fe(n,e?{add:an("add"),set:an("set"),delete:an("delete"),clear:an("clear")}:{add(r){!t&&!Ae(r)&&!Je(r)&&(r=z(r));const i=z(this);return cn(i).has.call(i,r)||(i.add(r),Ge(i,"add",r,r)),this},set(r,i){!t&&!Ae(i)&&!Je(i)&&(i=z(i));const l=z(this),{has:o,get:c}=cn(l);let u=o.call(l,r);u||(r=z(r),u=o.call(l,r));const a=c.call(l,r);return l.set(r,i),u?ot(i,a)&&Ge(l,"set",r,i):Ge(l,"add",r,i),this},delete(r){const i=z(this),{has:l,get:o}=cn(i);let c=l.call(i,r);c||(r=z(r),c=l.call(i,r)),o&&o.call(i,r);const u=i.delete(r);return c&&Ge(i,"delete",r,void 0),u},clear(){const r=z(this),i=r.size!==0,l=r.clear();return i&&Ge(r,"clear",void 0,void 0),l}}),["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=il(r,e,t)}),n}function Us(e,t){const n=ol(e,t);return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(Q(n,r)&&r in s?n:s,r,i)}const ll={get:Us(!1,!1)},cl={get:Us(!1,!0)},al={get:Us(!0,!1)};const mi=new WeakMap,vi=new WeakMap,yi=new WeakMap,fl=new WeakMap;function ul(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function dl(e){return e.__v_skip||!Object.isExtensible(e)?0:ul(No(e))}function Nt(e){return Je(e)?e:Bs(e,!1,nl,ll,mi)}function hl(e){return Bs(e,!1,rl,cl,vi)}function Yt(e){return Bs(e,!0,sl,al,yi)}function Bs(e,t,n,s,r){if(!te(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=dl(e);if(i===0)return e;const l=r.get(e);if(l)return l;const o=new Proxy(e,i===2?s:n);return r.set(e,o),o}function lt(e){return Je(e)?lt(e.__v_raw):!!(e&&e.__v_isReactive)}function Je(e){return!!(e&&e.__v_isReadonly)}function Ae(e){return!!(e&&e.__v_isShallow)}function Vn(e){return e?!!e.__v_raw:!1}function z(e){const t=e&&e.__v_raw;return t?z(t):e}function bn(e){return!Q(e,"__v_skip")&&Object.isExtensible(e)&&ei(e,"__v_skip",!0),e}const He=e=>te(e)?Nt(e):e,Ft=e=>te(e)?Yt(e):e;function ae(e){return e?e.__v_isRef===!0:!1}function yt(e){return _i(e,!1)}function Ie(e){return _i(e,!0)}function _i(e,t){return ae(e)?e:new pl(e,t)}class pl{constructor(t,n){this.dep=new $n,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:z(t),this._value=n?t:He(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Ae(t)||Je(t);t=s?t:z(t),ot(t,n)&&(this._rawValue=t,this._value=s?t:He(t),this.dep.trigger())}}function Wn(e){return ae(e)?e.value:e}function ce(e){return G(e)?e():Wn(e)}const gl={get:(e,t,n)=>t==="__v_raw"?e:Wn(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ae(r)&&!ae(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function bi(e){return lt(e)?e:new Proxy(e,gl)}class ml{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new $n,{get:s,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function vl(e){return new ml(e)}class yl{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0,this._raw=z(t);let r=!0,i=t;if(!B(t)||!Nn(String(n)))do r=!Vn(i)||Ae(i);while(r&&(i=i.__v_raw));this._shallow=r}get value(){let t=this._object[this._key];return this._shallow&&(t=Wn(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&ae(this._raw[this._key])){const n=this._object[this._key];if(ae(n)){n.value=t;return}}this._object[this._key]=t}get dep(){return Jo(this._raw,this._key)}}class _l{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function bl(e,t,n){return ae(e)?e:G(e)?new _l(e):te(e)&&arguments.length>1?wl(e,t,n):yt(e)}function wl(e,t,n){return new yl(e,t,n)}class Sl{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new $n(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Gt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&se!==this)return li(this,!0),!0}get value(){const t=this.dep.track();return fi(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function xl(e,t,n=!1){let s,r;return G(e)?s=e:(s=e.get,r=e.set),new Sl(s,r,n)}const fn={},En=new WeakMap;let pt;function Tl(e,t=!1,n=pt){if(n){let s=En.get(n);s||En.set(n,s=[]),s.push(e)}}function El(e,t,n=re){const{immediate:s,deep:r,once:i,scheduler:l,augmentJob:o,call:c}=n,u=g=>r?g:Ae(g)||r===!1||r===0?it(g,1):it(g);let a,h,v,_,C=!1,P=!1;if(ae(e)?(h=()=>e.value,C=Ae(e)):lt(e)?(h=()=>u(e),C=!0):B(e)?(P=!0,C=e.some(g=>lt(g)||Ae(g)),h=()=>e.map(g=>{if(ae(g))return g.value;if(lt(g))return u(g);if(G(g))return c?c(g,2):g()})):G(e)?t?h=c?()=>c(e,2):e:h=()=>{if(v){Xe();try{v()}finally{Ye()}}const g=pt;pt=a;try{return c?c(e,3,[_]):e(_)}finally{pt=g}}:h=ke,t&&r){const g=h,O=r===!0?1/0:r;h=()=>it(g(),O)}const K=ri(),H=()=>{a.stop(),K&&K.active&&Ds(K.effects,a)};if(i&&t){const g=t;t=(...O)=>{g(...O),H()}}let V=P?new Array(e.length).fill(fn):fn;const p=g=>{if(!(!(a.flags&1)||!a.dirty&&!g))if(t){const O=a.run();if(r||C||(P?O.some((W,R)=>ot(W,V[R])):ot(O,V))){v&&v();const W=pt;pt=a;try{const R=[O,V===fn?void 0:P&&V[0]===fn?[]:V,_];V=O,c?c(t,3,R):t(...R)}finally{pt=W}}}else a.run()};return o&&o(p),a=new ii(h),a.scheduler=l?()=>l(p,!1):p,_=g=>Tl(g,!1,a),v=a.onStop=()=>{const g=En.get(a);if(g){if(c)c(g,4);else for(const O of g)O();En.delete(a)}},t?s?p(!0):V=a.run():l?l(p.bind(null,!0),!0):a.run(),H.pause=a.pause.bind(a),H.resume=a.resume.bind(a),H.stop=H,H}function it(e,t=1/0,n){if(t<=0||!te(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,ae(e))it(e.value,t,n);else if(B(e))for(let s=0;s{it(s,t,n)});else if(Zr(e)){for(const s in e)it(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&it(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.27 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function sn(e,t,n,s){try{return s?e(...s):e()}catch(r){kn(r,t,n)}}function De(e,t,n,s){if(G(e)){const r=sn(e,t,n,s);return r&&zr(r)&&r.catch(i=>{kn(i,t,n)}),r}if(B(e)){const r=[];for(let i=0;i>>1,r=be[s],i=Jt(r);i=Jt(n)?be.push(e):be.splice(Al(t),0,e),e.flags|=1,Si()}}function Si(){Cn||(Cn=wi.then(xi))}function Rl(e){B(e)?Pt.push(...e):st&&e.id===-1?st.splice(Mt+1,0,e):e.flags&1||(Pt.push(e),e.flags|=1),Si()}function lr(e,t,n=Ve+1){for(;nJt(n)-Jt(s));if(Pt.length=0,st){st.push(...t);return}for(st=t,Mt=0;Mte.id==null?e.flags&2?-1:1/0:e.id;function xi(e){try{for(Ve=0;Ve{s._d&&In(-1);const i=Rn(t);let l;try{l=e(...r)}finally{Rn(i),s._d&&In(1)}return l};return s._n=!0,s._c=!0,s._d=!0,s}function We(e,t,n,s){const r=e.dirs,i=t&&t.dirs;for(let l=0;l1)return n&&G(t)?t.call(s&&s.proxy):t}}function Ei(){return!!(Et()||wt)}const Il=Symbol.for("v-scx"),Pl=()=>_t(Il);function Ci(e,t){return Bn(e,null,t)}function mf(e,t){return Bn(e,null,{flush:"post"})}function Pe(e,t,n){return Bn(e,t,n)}function Bn(e,t,n=re){const{immediate:s,deep:r,flush:i,once:l}=n,o=fe({},n),c=t&&s||!t&&i!=="post";let u;if(en){if(i==="sync"){const _=Pl();u=_.__watcherHandles||(_.__watcherHandles=[])}else if(!c){const _=()=>{};return _.stop=ke,_.resume=ke,_.pause=ke,_}}const a=ye;o.call=(_,C,P)=>De(_,a,C,P);let h=!1;i==="post"?o.scheduler=_=>{Ee(_,a&&a.suspense)}:i!=="sync"&&(h=!0,o.scheduler=(_,C)=>{C?_():Ks(_)}),o.augmentJob=_=>{t&&(_.flags|=4),h&&(_.flags|=2,a&&(_.id=a.uid,_.i=a))};const v=El(e,t,o);return en&&(u?u.push(v):c&&v()),v}function Ll(e,t,n){const s=this.proxy,r=le(e)?e.includes(".")?Ai(s,e):()=>s[e]:e.bind(s,s);let i;G(t)?i=t:(i=t.handler,n=t);const l=rn(this),o=Bn(r,i.bind(s),n);return l(),o}function Ai(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;re.__isTeleport,qe=Symbol("_leaveCb"),un=Symbol("_enterCb");function Fl(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Ht(()=>{e.isMounted=!0}),Di(()=>{e.isUnmounting=!0}),e}const Re=[Function,Array],Mi={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Re,onEnter:Re,onAfterEnter:Re,onEnterCancelled:Re,onBeforeLeave:Re,onLeave:Re,onAfterLeave:Re,onLeaveCancelled:Re,onBeforeAppear:Re,onAppear:Re,onAfterAppear:Re,onAppearCancelled:Re},Oi=e=>{const t=e.subTree;return t.component?Oi(t.component):t},Hl={name:"BaseTransition",props:Mi,setup(e,{slots:t}){const n=Et(),s=Fl();return()=>{const r=t.default&&Li(t.default(),!0);if(!r||!r.length)return;const i=Ii(r),l=z(e),{mode:o}=l;if(s.isLeaving)return rs(i);const c=cr(i);if(!c)return rs(i);let u=Es(c,l,s,n,h=>u=h);c.type!==ue&&zt(c,u);let a=n.subTree&&cr(n.subTree);if(a&&a.type!==ue&&!gt(a,c)&&Oi(n).type!==ue){let h=Es(a,l,s,n);if(zt(a,h),o==="out-in"&&c.type!==ue)return s.isLeaving=!0,h.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete h.afterLeave,a=void 0},rs(i);o==="in-out"&&c.type!==ue?h.delayLeave=(v,_,C)=>{const P=Pi(s,a);P[String(a.key)]=a,v[qe]=()=>{_(),v[qe]=void 0,delete u.delayedLeave,a=void 0},u.delayedLeave=()=>{C(),delete u.delayedLeave,a=void 0}}:a=void 0}else a&&(a=void 0);return i}}};function Ii(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==ue){t=n;break}}return t}const Dl=Hl;function Pi(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function Es(e,t,n,s,r){const{appear:i,mode:l,persisted:o=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:a,onEnterCancelled:h,onBeforeLeave:v,onLeave:_,onAfterLeave:C,onLeaveCancelled:P,onBeforeAppear:K,onAppear:H,onAfterAppear:V,onAppearCancelled:p}=t,g=String(e.key),O=Pi(n,e),W=(T,I)=>{T&&De(T,s,9,I)},R=(T,I)=>{const E=I[1];W(T,I),B(T)?T.every(y=>y.length<=1)&&E():T.length<=1&&E()},U={mode:l,persisted:o,beforeEnter(T){let I=c;if(!n.isMounted)if(i)I=K||c;else return;T[qe]&&T[qe](!0);const E=O[g];E&>(e,E)&&E.el[qe]&&E.el[qe](),W(I,[T])},enter(T){let I=u,E=a,y=h;if(!n.isMounted)if(i)I=H||u,E=V||a,y=p||h;else return;let N=!1;const Y=T[un]=ie=>{N||(N=!0,ie?W(y,[T]):W(E,[T]),U.delayedLeave&&U.delayedLeave(),T[un]=void 0)};I?R(I,[T,Y]):Y()},leave(T,I){const E=String(e.key);if(T[un]&&T[un](!0),n.isUnmounting)return I();W(v,[T]);let y=!1;const N=T[qe]=Y=>{y||(y=!0,I(),Y?W(P,[T]):W(C,[T]),T[qe]=void 0,O[E]===e&&delete O[E])};O[E]=e,_?R(_,[T,N]):N()},clone(T){const I=Es(T,t,n,s,r);return r&&r(I),I}};return U}function rs(e){if(Kn(e))return e=ct(e),e.children=null,e}function cr(e){if(!Kn(e))return Ri(e.type)&&e.children?Ii(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&G(n.default))return n.default()}}function zt(e,t){e.shapeFlag&6&&e.component?(e.transition=t,zt(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Li(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;iLt(C,t&&(B(t)?t[P]:t),n,s,r));return}if(bt(s)&&!r){s.shapeFlag&512&&s.type.__asyncResolved&&s.component.subTree.component&&Lt(e,t,n,s.component.subTree);return}const i=s.shapeFlag&4?Ys(s.component):s.el,l=r?null:i,{i:o,r:c}=e,u=t&&t.r,a=o.refs===re?o.refs={}:o.refs,h=o.setupState,v=z(h),_=h===re?Yr:C=>Q(v,C);if(u!=null&&u!==c){if(ar(t),le(u))a[u]=null,_(u)&&(h[u]=null);else if(ae(u)){u.value=null;const C=t;C.k&&(a[C.k]=null)}}if(G(c))sn(c,o,12,[l,a]);else{const C=le(c),P=ae(c);if(C||P){const K=()=>{if(e.f){const H=C?_(c)?h[c]:a[c]:c.value;if(r)B(H)&&Ds(H,i);else if(B(H))H.includes(i)||H.push(i);else if(C)a[c]=[i],_(c)&&(h[c]=a[c]);else{const V=[i];c.value=V,e.k&&(a[e.k]=V)}}else C?(a[c]=l,_(c)&&(h[c]=l)):P&&(c.value=l,e.k&&(a[e.k]=l))};if(l){const H=()=>{K(),Mn.delete(e)};H.id=-1,Mn.set(e,H),Ee(H,n)}else ar(e),K()}}}function ar(e){const t=Mn.get(e);t&&(t.flags|=8,Mn.delete(e))}let fr=!1;const Rt=()=>{fr||(console.error("Hydration completed but contains mismatches."),fr=!0)},$l=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",jl=e=>e.namespaceURI.includes("MathML"),dn=e=>{if(e.nodeType===1){if($l(e))return"svg";if(jl(e))return"mathml"}},hn=e=>e.nodeType===8;function Vl(e){const{mt:t,p:n,o:{patchProp:s,createText:r,nextSibling:i,parentNode:l,remove:o,insert:c,createComment:u}}=e,a=(p,g)=>{if(!g.hasChildNodes()){n(null,p,g),An(),g._vnode=p;return}h(g.firstChild,p,null,null,null),An(),g._vnode=p},h=(p,g,O,W,R,U=!1)=>{U=U||!!g.dynamicChildren;const T=hn(p)&&p.data==="[",I=()=>P(p,g,O,W,R,T),{type:E,ref:y,shapeFlag:N,patchFlag:Y}=g;let ie=p.nodeType;g.el=p,Y===-2&&(U=!1,g.dynamicChildren=null);let j=null;switch(E){case St:ie!==3?g.children===""?(c(g.el=r(""),l(p),p),j=p):j=I():(p.data!==g.children&&(Rt(),p.data=g.children),j=i(p));break;case ue:V(p)?(j=i(p),H(g.el=p.content.firstChild,p,O)):ie!==8||T?j=I():j=i(p);break;case Kt:if(T&&(p=i(p),ie=p.nodeType),ie===1||ie===3){j=p;const X=!g.children.length;for(let D=0;D{U=U||!!g.dynamicChildren;const{type:T,props:I,patchFlag:E,shapeFlag:y,dirs:N,transition:Y}=g,ie=T==="input"||T==="option";if(ie||E!==-1){N&&We(g,null,O,"created");let j=!1;if(V(p)){j=to(null,Y)&&O&&O.vnode.props&&O.vnode.props.appear;const D=p.content.firstChild;if(j){const ee=D.getAttribute("class");ee&&(D.$cls=ee),Y.beforeEnter(D)}H(D,p,O),g.el=p=D}if(y&16&&!(I&&(I.innerHTML||I.textContent))){let D=_(p.firstChild,g,p,O,W,R,U);for(;D;){pn(p,1)||Rt();const ee=D;D=D.nextSibling,o(ee)}}else if(y&8){let D=g.children;D[0]===` +`&&(p.tagName==="PRE"||p.tagName==="TEXTAREA")&&(D=D.slice(1));const{textContent:ee}=p;ee!==D&&ee!==D.replace(/\r\n|\r/g,` +`)&&(pn(p,0)||Rt(),p.textContent=g.children)}if(I){if(ie||!U||E&48){const D=p.tagName.includes("-");for(const ee in I)(ie&&(ee.endsWith("value")||ee==="indeterminate")||nn(ee)&&!mt(ee)||ee[0]==="."||D&&!mt(ee))&&s(p,ee,null,I[ee],void 0,O)}else if(I.onClick)s(p,"onClick",null,I.onClick,void 0,O);else if(E&4&<(I.style))for(const D in I.style)I.style[D]}let X;(X=I&&I.onVnodeBeforeMount)&&Me(X,O,g),N&&We(g,null,O,"beforeMount"),((X=I&&I.onVnodeMounted)||N||j)&&oo(()=>{X&&Me(X,O,g),j&&Y.enter(p),N&&We(g,null,O,"mounted")},W)}return p.nextSibling},_=(p,g,O,W,R,U,T)=>{T=T||!!g.dynamicChildren;const I=g.children,E=I.length;for(let y=0;y{const{slotScopeIds:T}=g;T&&(R=R?R.concat(T):T);const I=l(p),E=_(i(p),g,I,O,W,R,U);return E&&hn(E)&&E.data==="]"?i(g.anchor=E):(Rt(),c(g.anchor=u("]"),I,E),E)},P=(p,g,O,W,R,U)=>{if(pn(p.parentElement,1)||Rt(),g.el=null,U){const E=K(p);for(;;){const y=i(p);if(y&&y!==E)o(y);else break}}const T=i(p),I=l(p);return o(p),n(null,g,I,T,O,W,dn(I),R),O&&(O.vnode.el=g.el,qi(O,g.el)),T},K=(p,g="[",O="]")=>{let W=0;for(;p;)if(p=i(p),p&&hn(p)&&(p.data===g&&W++,p.data===O)){if(W===0)return i(p);W--}return p},H=(p,g,O)=>{const W=g.parentNode;W&&W.replaceChild(p,g);let R=O;for(;R;)R.vnode.el===g&&(R.vnode.el=R.subTree.el=p),R=R.parent},V=p=>p.nodeType===1&&p.tagName==="TEMPLATE";return[a,h]}const ur="data-allow-mismatch",Wl={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function pn(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(ur);)e=e.parentElement;const n=e&&e.getAttribute(ur);if(n==null)return!1;if(n==="")return!0;{const s=n.split(",");return t===0&&s.includes("children")?!0:s.includes(Wl[t])}}Dn().requestIdleCallback;Dn().cancelIdleCallback;const bt=e=>!!e.type.__asyncLoader,Kn=e=>e.type.__isKeepAlive;function kl(e,t){Hi(e,"a",t)}function Ul(e,t){Hi(e,"da",t)}function Hi(e,t,n=ye){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(qn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)Kn(r.parent.vnode)&&Bl(s,t,n,r),r=r.parent}}function Bl(e,t,n,s){const r=qn(t,e,s,!0);Gn(()=>{Ds(s[t],r)},n)}function qn(e,t,n=ye,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...l)=>{Xe();const o=rn(n),c=De(t,n,e,l);return o(),Ye(),c});return s?r.unshift(i):r.push(i),i}}const et=e=>(t,n=ye)=>{(!en||e==="sp")&&qn(e,(...s)=>t(...s),n)},Kl=et("bm"),Ht=et("m"),ql=et("bu"),Gl=et("u"),Di=et("bum"),Gn=et("um"),Xl=et("sp"),Yl=et("rtg"),Jl=et("rtc");function zl(e,t=ye){qn("ec",e,t)}const $i="components";function vf(e,t){return Vi($i,e,!0,t)||e}const ji=Symbol.for("v-ndc");function yf(e){return le(e)?Vi($i,e,!1)||e:e||ji}function Vi(e,t,n=!0,s=!1){const r=we||ye;if(r){const i=r.type;{const o=Pc(i,!1);if(o&&(o===t||o===Le(t)||o===Hn(Le(t))))return i}const l=dr(r[e]||i[e],t)||dr(r.appContext[e],t);return!l&&s?i:l}}function dr(e,t){return e&&(e[t]||e[Le(t)]||e[Hn(Le(t))])}function _f(e,t,n,s){let r;const i=n,l=B(e);if(l||le(e)){const o=l&<(e);let c=!1,u=!1;o&&(c=!Ae(e),u=Je(e),e=jn(e)),r=new Array(e.length);for(let a=0,h=e.length;at(o,c,void 0,i));else{const o=Object.keys(e);r=new Array(o.length);for(let c=0,u=o.length;c0;return t!=="default"&&(n.name=t),Os(),Is(ve,null,[de("slot",n,s&&s())],u?-2:64)}let i=e[t];i&&i._c&&(i._d=!1),Os();const l=i&&Wi(i(n)),o=n.key||l&&l.key,c=Is(ve,{key:(o&&!Ze(o)?o:`_${t}`)+(!l&&s?"_fb":"")},l||(s?s():[]),l&&e._===1?64:-2);return!r&&c.scopeId&&(c.slotScopeIds=[c.scopeId+"-s"]),i&&i._c&&(i._d=!0),c}function Wi(e){return e.some(t=>Zt(t)?!(t.type===ue||t.type===ve&&!Wi(t.children)):!0)?e:null}function wf(e,t){const n={};for(const s in e)n[/[A-Z]/.test(s)?`on:${s}`:_n(s)]=e[s];return n}const Cs=e=>e?uo(e)?Ys(e):Cs(e.parent):null,Bt=fe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Cs(e.parent),$root:e=>Cs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Ui(e),$forceUpdate:e=>e.f||(e.f=()=>{Ks(e.update)}),$nextTick:e=>e.n||(e.n=Un.bind(e.proxy)),$watch:e=>Ll.bind(e)}),is=(e,t)=>e!==re&&!e.__isScriptSetup&&Q(e,t),Ql={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:l,type:o,appContext:c}=e;if(t[0]!=="$"){const v=l[t];if(v!==void 0)switch(v){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(is(s,t))return l[t]=1,s[t];if(r!==re&&Q(r,t))return l[t]=2,r[t];if(Q(i,t))return l[t]=3,i[t];if(n!==re&&Q(n,t))return l[t]=4,n[t];As&&(l[t]=0)}}const u=Bt[t];let a,h;if(u)return t==="$attrs"&&me(e.attrs,"get",""),u(e);if((a=o.__cssModules)&&(a=a[t]))return a;if(n!==re&&Q(n,t))return l[t]=4,n[t];if(h=c.config.globalProperties,Q(h,t))return h[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return is(r,t)?(r[t]=n,!0):s!==re&&Q(s,t)?(s[t]=n,!0):Q(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,props:i,type:l}},o){let c;return!!(n[o]||e!==re&&o[0]!=="$"&&Q(e,o)||is(t,o)||Q(i,o)||Q(s,o)||Q(Bt,o)||Q(r.config.globalProperties,o)||(c=l.__cssModules)&&c[o])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Q(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Sf(){return Zl().slots}function Zl(e){const t=Et();return t.setupContext||(t.setupContext=po(t))}function hr(e){return B(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let As=!0;function ec(e){const t=Ui(e),n=e.proxy,s=e.ctx;As=!1,t.beforeCreate&&pr(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:l,watch:o,provide:c,inject:u,created:a,beforeMount:h,mounted:v,beforeUpdate:_,updated:C,activated:P,deactivated:K,beforeDestroy:H,beforeUnmount:V,destroyed:p,unmounted:g,render:O,renderTracked:W,renderTriggered:R,errorCaptured:U,serverPrefetch:T,expose:I,inheritAttrs:E,components:y,directives:N,filters:Y}=t;if(u&&tc(u,s,null),l)for(const X in l){const D=l[X];G(D)&&(s[X]=D.bind(n))}if(r){const X=r.call(n,n);te(X)&&(e.data=Nt(X))}if(As=!0,i)for(const X in i){const D=i[X],ee=G(D)?D.bind(n,n):G(D.get)?D.get.bind(n,n):ke,on=!G(D)&&G(D.set)?D.set.bind(n):ke,ft=oe({get:ee,set:on});Object.defineProperty(s,X,{enumerable:!0,configurable:!0,get:()=>ft.value,set:$e=>ft.value=$e})}if(o)for(const X in o)ki(o[X],s,n,X);if(c){const X=G(c)?c.call(n):c;Reflect.ownKeys(X).forEach(D=>{Ol(D,X[D])})}a&&pr(a,e,"c");function j(X,D){B(D)?D.forEach(ee=>X(ee.bind(n))):D&&X(D.bind(n))}if(j(Kl,h),j(Ht,v),j(ql,_),j(Gl,C),j(kl,P),j(Ul,K),j(zl,U),j(Jl,W),j(Yl,R),j(Di,V),j(Gn,g),j(Xl,T),B(I))if(I.length){const X=e.exposed||(e.exposed={});I.forEach(D=>{Object.defineProperty(X,D,{get:()=>n[D],set:ee=>n[D]=ee,enumerable:!0})})}else e.exposed||(e.exposed={});O&&e.render===ke&&(e.render=O),E!=null&&(e.inheritAttrs=E),y&&(e.components=y),N&&(e.directives=N),T&&Fi(e)}function tc(e,t,n=ke){B(e)&&(e=Rs(e));for(const s in e){const r=e[s];let i;te(r)?"default"in r?i=_t(r.from||s,r.default,!0):i=_t(r.from||s):i=_t(r),ae(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:l=>i.value=l}):t[s]=i}}function pr(e,t,n){De(B(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function ki(e,t,n,s){let r=s.includes(".")?Ai(n,s):()=>n[s];if(le(e)){const i=t[e];G(i)&&Pe(r,i)}else if(G(e))Pe(r,e.bind(n));else if(te(e))if(B(e))e.forEach(i=>ki(i,t,n,s));else{const i=G(e.handler)?e.handler.bind(n):t[e.handler];G(i)&&Pe(r,i,e)}}function Ui(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:l}}=e.appContext,o=i.get(t);let c;return o?c=o:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(u=>On(c,u,l,!0)),On(c,t,l)),te(t)&&i.set(t,c),c}function On(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&On(e,i,n,!0),r&&r.forEach(l=>On(e,l,n,!0));for(const l in t)if(!(s&&l==="expose")){const o=nc[l]||n&&n[l];e[l]=o?o(e[l],t[l]):t[l]}return e}const nc={data:gr,props:mr,emits:mr,methods:Wt,computed:Wt,beforeCreate:_e,created:_e,beforeMount:_e,mounted:_e,beforeUpdate:_e,updated:_e,beforeDestroy:_e,beforeUnmount:_e,destroyed:_e,unmounted:_e,activated:_e,deactivated:_e,errorCaptured:_e,serverPrefetch:_e,components:Wt,directives:Wt,watch:rc,provide:gr,inject:sc};function gr(e,t){return t?e?function(){return fe(G(e)?e.call(this,this):e,G(t)?t.call(this,this):t)}:t:e}function sc(e,t){return Wt(Rs(e),Rs(t))}function Rs(e){if(B(e)){const t={};for(let n=0;nt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Le(t)}Modifiers`]||e[`${at(t)}Modifiers`];function cc(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||re;let r=n;const i=t.startsWith("update:"),l=i&&lc(s,t.slice(7));l&&(l.trim&&(r=n.map(a=>le(a)?a.trim():a)),l.number&&(r=n.map(Do)));let o,c=s[o=_n(t)]||s[o=_n(Le(t))];!c&&i&&(c=s[o=_n(at(t))]),c&&De(c,e,6,r);const u=s[o+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[o])return;e.emitted[o]=!0,De(u,e,6,r)}}const ac=new WeakMap;function Ki(e,t,n=!1){const s=n?ac:t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let l={},o=!1;if(!G(e)){const c=u=>{const a=Ki(u,t,!0);a&&(o=!0,fe(l,a))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!o?(te(e)&&s.set(e,null),null):(B(i)?i.forEach(c=>l[c]=null):fe(l,i),te(e)&&s.set(e,l),l)}function Xn(e,t){return!e||!nn(t)?!1:(t=t.slice(2).replace(/Once$/,""),Q(e,t[0].toLowerCase()+t.slice(1))||Q(e,at(t))||Q(e,t))}function os(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:l,attrs:o,emit:c,render:u,renderCache:a,props:h,data:v,setupState:_,ctx:C,inheritAttrs:P}=e,K=Rn(e);let H,V;try{if(n.shapeFlag&4){const g=r||s,O=g;H=Oe(u.call(O,g,a,h,_,v,C)),V=o}else{const g=t;H=Oe(g.length>1?g(h,{attrs:o,slots:l,emit:c}):g(h,null)),V=t.props?o:fc(o)}}catch(g){qt.length=0,kn(g,e,1),H=de(ue)}let p=H;if(V&&P!==!1){const g=Object.keys(V),{shapeFlag:O}=p;g.length&&O&7&&(i&&g.some(Hs)&&(V=uc(V,i)),p=ct(p,V,!1,!0))}return n.dirs&&(p=ct(p,null,!1,!0),p.dirs=p.dirs?p.dirs.concat(n.dirs):n.dirs),n.transition&&zt(p,n.transition),H=p,Rn(K),H}const fc=e=>{let t;for(const n in e)(n==="class"||n==="style"||nn(n))&&((t||(t={}))[n]=e[n]);return t},uc=(e,t)=>{const n={};for(const s in e)(!Hs(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function dc(e,t,n){const{props:s,children:r,component:i}=e,{props:l,children:o,patchFlag:c}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?vr(s,l,u):!!l;if(c&8){const a=t.dynamicProps;for(let h=0;hObject.create(Gi),Yi=e=>Object.getPrototypeOf(e)===Gi;function hc(e,t,n,s=!1){const r={},i=Xi();e.propsDefaults=Object.create(null),Ji(e,t,r,i);for(const l in e.propsOptions[0])l in r||(r[l]=void 0);n?e.props=s?r:hl(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function pc(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:l}}=e,o=z(r),[c]=e.propsOptions;let u=!1;if((s||l>0)&&!(l&16)){if(l&8){const a=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[v,_]=zi(h,t,!0);fe(l,v),_&&o.push(..._)};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}if(!i&&!c)return te(e)&&s.set(e,Ot),Ot;if(B(i))for(let a=0;ae==="_"||e==="_ctx"||e==="$stable",Gs=e=>B(e)?e.map(Oe):[Oe(e)],mc=(e,t,n)=>{if(t._n)return t;const s=Ml((...r)=>Gs(t(...r)),n);return s._c=!1,s},Qi=(e,t,n)=>{const s=e._ctx;for(const r in e){if(qs(r))continue;const i=e[r];if(G(i))t[r]=mc(r,i,s);else if(i!=null){const l=Gs(i);t[r]=()=>l}}},Zi=(e,t)=>{const n=Gs(t);e.slots.default=()=>n},eo=(e,t,n)=>{for(const s in t)(n||!qs(s))&&(e[s]=t[s])},vc=(e,t,n)=>{const s=e.slots=Xi();if(e.vnode.shapeFlag&32){const r=t._;r?(eo(s,t,n),n&&ei(s,"_",r,!0)):Qi(t,s)}else t&&Zi(e,t)},yc=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,l=re;if(s.shapeFlag&32){const o=t._;o?n&&o===1?i=!1:eo(r,t,n):(i=!t.$stable,Qi(t,r)),l=t}else t&&(Zi(e,t),l={default:1});if(i)for(const o in r)!qs(o)&&l[o]==null&&delete r[o]},Ee=oo;function _c(e){return bc(e,Vl)}function bc(e,t){const n=Dn();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:l,createText:o,createComment:c,setText:u,setElementText:a,parentNode:h,nextSibling:v,setScopeId:_=ke,insertStaticContent:C}=e,P=(f,d,m,x=null,b=null,w=null,L=void 0,M=null,A=!!d.dynamicChildren)=>{if(f===d)return;f&&!gt(f,d)&&(x=ln(f),$e(f,b,w,!0),f=null),d.patchFlag===-2&&(A=!1,d.dynamicChildren=null);const{type:S,ref:k,shapeFlag:F}=d;switch(S){case St:K(f,d,m,x);break;case ue:H(f,d,m,x);break;case Kt:f==null&&V(d,m,x,L);break;case ve:y(f,d,m,x,b,w,L,M,A);break;default:F&1?O(f,d,m,x,b,w,L,M,A):F&6?N(f,d,m,x,b,w,L,M,A):(F&64||F&128)&&S.process(f,d,m,x,b,w,L,M,A,Ct)}k!=null&&b?Lt(k,f&&f.ref,w,d||f,!d):k==null&&f&&f.ref!=null&&Lt(f.ref,null,w,f,!0)},K=(f,d,m,x)=>{if(f==null)s(d.el=o(d.children),m,x);else{const b=d.el=f.el;d.children!==f.children&&u(b,d.children)}},H=(f,d,m,x)=>{f==null?s(d.el=c(d.children||""),m,x):d.el=f.el},V=(f,d,m,x)=>{[f.el,f.anchor]=C(f.children,d,m,x,f.el,f.anchor)},p=({el:f,anchor:d},m,x)=>{let b;for(;f&&f!==d;)b=v(f),s(f,m,x),f=b;s(d,m,x)},g=({el:f,anchor:d})=>{let m;for(;f&&f!==d;)m=v(f),r(f),f=m;r(d)},O=(f,d,m,x,b,w,L,M,A)=>{if(d.type==="svg"?L="svg":d.type==="math"&&(L="mathml"),f==null)W(d,m,x,b,w,L,M,A);else{const S=f.el&&f.el._isVueCE?f.el:null;try{S&&S._beginPatch(),T(f,d,b,w,L,M,A)}finally{S&&S._endPatch()}}},W=(f,d,m,x,b,w,L,M)=>{let A,S;const{props:k,shapeFlag:F,transition:$,dirs:q}=f;if(A=f.el=l(f.type,w,k&&k.is,k),F&8?a(A,f.children):F&16&&U(f.children,A,null,x,b,ls(f,w),L,M),q&&We(f,null,x,"created"),R(A,f,f.scopeId,L,x),k){for(const ne in k)ne!=="value"&&!mt(ne)&&i(A,ne,null,k[ne],w,x);"value"in k&&i(A,"value",null,k.value,w),(S=k.onVnodeBeforeMount)&&Me(S,x,f)}q&&We(f,null,x,"beforeMount");const J=to(b,$);J&&$.beforeEnter(A),s(A,d,m),((S=k&&k.onVnodeMounted)||J||q)&&Ee(()=>{S&&Me(S,x,f),J&&$.enter(A),q&&We(f,null,x,"mounted")},b)},R=(f,d,m,x,b)=>{if(m&&_(f,m),x)for(let w=0;w{for(let S=A;S{const M=d.el=f.el;let{patchFlag:A,dynamicChildren:S,dirs:k}=d;A|=f.patchFlag&16;const F=f.props||re,$=d.props||re;let q;if(m&&ut(m,!1),(q=$.onVnodeBeforeUpdate)&&Me(q,m,d,f),k&&We(d,f,m,"beforeUpdate"),m&&ut(m,!0),(F.innerHTML&&$.innerHTML==null||F.textContent&&$.textContent==null)&&a(M,""),S?I(f.dynamicChildren,S,M,m,x,ls(d,b),w):L||D(f,d,M,null,m,x,ls(d,b),w,!1),A>0){if(A&16)E(M,F,$,m,b);else if(A&2&&F.class!==$.class&&i(M,"class",null,$.class,b),A&4&&i(M,"style",F.style,$.style,b),A&8){const J=d.dynamicProps;for(let ne=0;ne{q&&Me(q,m,d,f),k&&We(d,f,m,"updated")},x)},I=(f,d,m,x,b,w,L)=>{for(let M=0;M{if(d!==m){if(d!==re)for(const w in d)!mt(w)&&!(w in m)&&i(f,w,d[w],null,b,x);for(const w in m){if(mt(w))continue;const L=m[w],M=d[w];L!==M&&w!=="value"&&i(f,w,M,L,b,x)}"value"in m&&i(f,"value",d.value,m.value,b)}},y=(f,d,m,x,b,w,L,M,A)=>{const S=d.el=f?f.el:o(""),k=d.anchor=f?f.anchor:o("");let{patchFlag:F,dynamicChildren:$,slotScopeIds:q}=d;q&&(M=M?M.concat(q):q),f==null?(s(S,m,x),s(k,m,x),U(d.children||[],m,k,b,w,L,M,A)):F>0&&F&64&&$&&f.dynamicChildren&&f.dynamicChildren.length===$.length?(I(f.dynamicChildren,$,m,b,w,L,M),(d.key!=null||b&&d===b.subTree)&&no(f,d,!0)):D(f,d,m,k,b,w,L,M,A)},N=(f,d,m,x,b,w,L,M,A)=>{d.slotScopeIds=M,f==null?d.shapeFlag&512?b.ctx.activate(d,m,x,L,A):Y(d,m,x,b,w,L,A):ie(f,d,A)},Y=(f,d,m,x,b,w,L)=>{const M=f.component=Rc(f,x,b);if(Kn(f)&&(M.ctx.renderer=Ct),Mc(M,!1,L),M.asyncDep){if(b&&b.registerDep(M,j,L),!f.el){const A=M.subTree=de(ue);H(null,A,d,m),f.placeholder=A.el}}else j(M,f,d,m,b,w,L)},ie=(f,d,m)=>{const x=d.component=f.component;if(dc(f,d,m))if(x.asyncDep&&!x.asyncResolved){X(x,d,m);return}else x.next=d,x.update();else d.el=f.el,x.vnode=d},j=(f,d,m,x,b,w,L)=>{const M=()=>{if(f.isMounted){let{next:F,bu:$,u:q,parent:J,vnode:ne}=f;{const xe=so(f);if(xe){F&&(F.el=ne.el,X(f,F,L)),xe.asyncDep.then(()=>{f.isUnmounted||M()});return}}let Z=F,Se;ut(f,!1),F?(F.el=ne.el,X(f,F,L)):F=ne,$&&Zn($),(Se=F.props&&F.props.onVnodeBeforeUpdate)&&Me(Se,J,F,ne),ut(f,!0);const he=os(f),Ne=f.subTree;f.subTree=he,P(Ne,he,h(Ne.el),ln(Ne),f,b,w),F.el=he.el,Z===null&&qi(f,he.el),q&&Ee(q,b),(Se=F.props&&F.props.onVnodeUpdated)&&Ee(()=>Me(Se,J,F,ne),b)}else{let F;const{el:$,props:q}=d,{bm:J,m:ne,parent:Z,root:Se,type:he}=f,Ne=bt(d);if(ut(f,!1),J&&Zn(J),!Ne&&(F=q&&q.onVnodeBeforeMount)&&Me(F,Z,d),ut(f,!0),$&&Qn){const xe=()=>{f.subTree=os(f),Qn($,f.subTree,f,b,null)};Ne&&he.__asyncHydrate?he.__asyncHydrate($,f,xe):xe()}else{Se.ce&&Se.ce._def.shadowRoot!==!1&&Se.ce._injectChildStyle(he);const xe=f.subTree=os(f);P(null,xe,m,x,f,b,w),d.el=xe.el}if(ne&&Ee(ne,b),!Ne&&(F=q&&q.onVnodeMounted)){const xe=d;Ee(()=>Me(F,Z,xe),b)}(d.shapeFlag&256||Z&&bt(Z.vnode)&&Z.vnode.shapeFlag&256)&&f.a&&Ee(f.a,b),f.isMounted=!0,d=m=x=null}};f.scope.on();const A=f.effect=new ii(M);f.scope.off();const S=f.update=A.run.bind(A),k=f.job=A.runIfDirty.bind(A);k.i=f,k.id=f.uid,A.scheduler=()=>Ks(k),ut(f,!0),S()},X=(f,d,m)=>{d.component=f;const x=f.vnode.props;f.vnode=d,f.next=null,pc(f,d.props,x,m),yc(f,d.children,m),Xe(),lr(f),Ye()},D=(f,d,m,x,b,w,L,M,A=!1)=>{const S=f&&f.children,k=f?f.shapeFlag:0,F=d.children,{patchFlag:$,shapeFlag:q}=d;if($>0){if($&128){on(S,F,m,x,b,w,L,M,A);return}else if($&256){ee(S,F,m,x,b,w,L,M,A);return}}q&8?(k&16&&Dt(S,b,w),F!==S&&a(m,F)):k&16?q&16?on(S,F,m,x,b,w,L,M,A):Dt(S,b,w,!0):(k&8&&a(m,""),q&16&&U(F,m,x,b,w,L,M,A))},ee=(f,d,m,x,b,w,L,M,A)=>{f=f||Ot,d=d||Ot;const S=f.length,k=d.length,F=Math.min(S,k);let $;for($=0;$k?Dt(f,b,w,!0,!1,F):U(d,m,x,b,w,L,M,A,F)},on=(f,d,m,x,b,w,L,M,A)=>{let S=0;const k=d.length;let F=f.length-1,$=k-1;for(;S<=F&&S<=$;){const q=f[S],J=d[S]=A?rt(d[S]):Oe(d[S]);if(gt(q,J))P(q,J,m,null,b,w,L,M,A);else break;S++}for(;S<=F&&S<=$;){const q=f[F],J=d[$]=A?rt(d[$]):Oe(d[$]);if(gt(q,J))P(q,J,m,null,b,w,L,M,A);else break;F--,$--}if(S>F){if(S<=$){const q=$+1,J=q$)for(;S<=F;)$e(f[S],b,w,!0),S++;else{const q=S,J=S,ne=new Map;for(S=J;S<=$;S++){const Te=d[S]=A?rt(d[S]):Oe(d[S]);Te.key!=null&&ne.set(Te.key,S)}let Z,Se=0;const he=$-J+1;let Ne=!1,xe=0;const $t=new Array(he);for(S=0;S=he){$e(Te,b,w,!0);continue}let je;if(Te.key!=null)je=ne.get(Te.key);else for(Z=J;Z<=$;Z++)if($t[Z-J]===0&>(Te,d[Z])){je=Z;break}je===void 0?$e(Te,b,w,!0):($t[je-J]=S+1,je>=xe?xe=je:Ne=!0,P(Te,d[je],m,null,b,w,L,M,A),Se++)}const tr=Ne?wc($t):Ot;for(Z=tr.length-1,S=he-1;S>=0;S--){const Te=J+S,je=d[Te],nr=d[Te+1],sr=Te+1{const{el:w,type:L,transition:M,children:A,shapeFlag:S}=f;if(S&6){ft(f.component.subTree,d,m,x);return}if(S&128){f.suspense.move(d,m,x);return}if(S&64){L.move(f,d,m,Ct);return}if(L===ve){s(w,d,m);for(let F=0;FM.enter(w),b);else{const{leave:F,delayLeave:$,afterLeave:q}=M,J=()=>{f.ctx.isUnmounted?r(w):s(w,d,m)},ne=()=>{w._isLeaving&&w[qe](!0),F(w,()=>{J(),q&&q()})};$?$(w,J,ne):ne()}else s(w,d,m)},$e=(f,d,m,x=!1,b=!1)=>{const{type:w,props:L,ref:M,children:A,dynamicChildren:S,shapeFlag:k,patchFlag:F,dirs:$,cacheIndex:q}=f;if(F===-2&&(b=!1),M!=null&&(Xe(),Lt(M,null,m,f,!0),Ye()),q!=null&&(d.renderCache[q]=void 0),k&256){d.ctx.deactivate(f);return}const J=k&1&&$,ne=!bt(f);let Z;if(ne&&(Z=L&&L.onVnodeBeforeUnmount)&&Me(Z,d,f),k&6)Po(f.component,m,x);else{if(k&128){f.suspense.unmount(m,x);return}J&&We(f,null,d,"beforeUnmount"),k&64?f.type.remove(f,d,m,Ct,x):S&&!S.hasOnce&&(w!==ve||F>0&&F&64)?Dt(S,d,m,!1,!0):(w===ve&&F&384||!b&&k&16)&&Dt(A,d,m),x&&Zs(f)}(ne&&(Z=L&&L.onVnodeUnmounted)||J)&&Ee(()=>{Z&&Me(Z,d,f),J&&We(f,null,d,"unmounted")},m)},Zs=f=>{const{type:d,el:m,anchor:x,transition:b}=f;if(d===ve){Io(m,x);return}if(d===Kt){g(f);return}const w=()=>{r(m),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(f.shapeFlag&1&&b&&!b.persisted){const{leave:L,delayLeave:M}=b,A=()=>L(m,w);M?M(f.el,w,A):A()}else w()},Io=(f,d)=>{let m;for(;f!==d;)m=v(f),r(f),f=m;r(d)},Po=(f,d,m)=>{const{bum:x,scope:b,job:w,subTree:L,um:M,m:A,a:S}=f;_r(A),_r(S),x&&Zn(x),b.stop(),w&&(w.flags|=8,$e(L,f,d,m)),M&&Ee(M,d),Ee(()=>{f.isUnmounted=!0},d)},Dt=(f,d,m,x=!1,b=!1,w=0)=>{for(let L=w;L{if(f.shapeFlag&6)return ln(f.component.subTree);if(f.shapeFlag&128)return f.suspense.next();const d=v(f.anchor||f.el),m=d&&d[Nl];return m?v(m):d};let Jn=!1;const er=(f,d,m)=>{let x;f==null?d._vnode&&($e(d._vnode,null,null,!0),x=d._vnode.component):P(d._vnode||null,f,d,null,null,null,m),d._vnode=f,Jn||(Jn=!0,lr(x),An(),Jn=!1)},Ct={p:P,um:$e,m:ft,r:Zs,mt:Y,mc:U,pc:D,pbc:I,n:ln,o:e};let zn,Qn;return t&&([zn,Qn]=t(Ct)),{render:er,hydrate:zn,createApp:oc(er,zn)}}function ls({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function ut({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function to(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function no(e,t,n=!1){const s=e.children,r=t.children;if(B(s)&&B(r))for(let i=0;i>1,e[n[o]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,l=n[i-1];i-- >0;)n[i]=l,l=t[l];return n}function so(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:so(t)}function _r(e){if(e)for(let t=0;te.__isSuspense;function oo(e,t){t&&t.pendingBranch?B(e)?t.effects.push(...e):t.effects.push(e):Rl(e)}const ve=Symbol.for("v-fgt"),St=Symbol.for("v-txt"),ue=Symbol.for("v-cmt"),Kt=Symbol.for("v-stc"),qt=[];let Ce=null;function Os(e=!1){qt.push(Ce=e?null:[])}function Sc(){qt.pop(),Ce=qt[qt.length-1]||null}let Qt=1;function In(e,t=!1){Qt+=e,e<0&&Ce&&t&&(Ce.hasOnce=!0)}function lo(e){return e.dynamicChildren=Qt>0?Ce||Ot:null,Sc(),Qt>0&&Ce&&Ce.push(e),e}function xf(e,t,n,s,r,i){return lo(ao(e,t,n,s,r,i,!0))}function Is(e,t,n,s,r){return lo(de(e,t,n,s,r,!0))}function Zt(e){return e?e.__v_isVNode===!0:!1}function gt(e,t){return e.type===t.type&&e.key===t.key}const co=({key:e})=>e??null,wn=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?le(e)||ae(e)||G(e)?{i:we,r:e,k:t,f:!!n}:e:null);function ao(e,t=null,n=null,s=0,r=null,i=e===ve?0:1,l=!1,o=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&co(t),ref:t&&wn(t),scopeId:Ti,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:we};return o?(Xs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=le(n)?8:16),Qt>0&&!l&&Ce&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Ce.push(c),c}const de=xc;function xc(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===ji)&&(e=ue),Zt(e)){const o=ct(e,t,!0);return n&&Xs(o,n),Qt>0&&!i&&Ce&&(o.shapeFlag&6?Ce[Ce.indexOf(e)]=o:Ce.push(o)),o.patchFlag=-2,o}if(Lc(e)&&(e=e.__vccOpts),t){t=Tc(t);let{class:o,style:c}=t;o&&!le(o)&&(t.class=js(o)),te(c)&&(Vn(c)&&!B(c)&&(c=fe({},c)),t.style=$s(c))}const l=le(e)?1:io(e)?128:Ri(e)?64:te(e)?4:G(e)?2:0;return ao(e,t,n,s,r,l,i,!0)}function Tc(e){return e?Vn(e)||Yi(e)?fe({},e):e:null}function ct(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:l,children:o,transition:c}=e,u=t?Ec(r||{},t):r,a={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&co(u),ref:t&&t.ref?n&&i?B(i)?i.concat(wn(t)):[i,wn(t)]:wn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ve?l===-1?16:l|16:l,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&ct(e.ssContent),ssFallback:e.ssFallback&&ct(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&zt(a,c.clone(a)),a}function fo(e=" ",t=0){return de(St,null,e,t)}function Tf(e,t){const n=de(Kt,null,e);return n.staticCount=t,n}function Ef(e="",t=!1){return t?(Os(),Is(ue,null,e)):de(ue,null,e)}function Oe(e){return e==null||typeof e=="boolean"?de(ue):B(e)?de(ve,null,e.slice()):Zt(e)?rt(e):de(St,null,String(e))}function rt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:ct(e)}function Xs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(B(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Xs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Yi(t)?t._ctx=we:r===3&&we&&(we.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else G(t)?(t={default:t,_ctx:we},n=32):(t=String(t),s&64?(n=16,t=[fo(t)]):n=8);e.children=t,e.shapeFlag|=n}function Ec(...e){const t={};for(let n=0;nye||we;let Pn,Ps;{const e=Dn(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(l=>l(i)):r[0](i)}};Pn=t("__VUE_INSTANCE_SETTERS__",n=>ye=n),Ps=t("__VUE_SSR_SETTERS__",n=>en=n)}const rn=e=>{const t=ye;return Pn(e),e.scope.on(),()=>{e.scope.off(),Pn(t)}},br=()=>{ye&&ye.scope.off(),Pn(null)};function uo(e){return e.vnode.shapeFlag&4}let en=!1;function Mc(e,t=!1,n=!1){t&&Ps(t);const{props:s,children:r}=e.vnode,i=uo(e);hc(e,s,i,t),vc(e,r,n||t);const l=i?Oc(e,t):void 0;return t&&Ps(!1),l}function Oc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Ql);const{setup:s}=n;if(s){Xe();const r=e.setupContext=s.length>1?po(e):null,i=rn(e),l=sn(s,e,0,[e.props,r]),o=zr(l);if(Ye(),i(),(o||e.sp)&&!bt(e)&&Fi(e),o){if(l.then(br,br),t)return l.then(c=>{wr(e,c)}).catch(c=>{kn(c,e,0)});e.asyncDep=l}else wr(e,l)}else ho(e)}function wr(e,t,n){G(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:te(t)&&(e.setupState=bi(t)),ho(e)}function ho(e,t,n){const s=e.type;e.render||(e.render=s.render||ke);{const r=rn(e);Xe();try{ec(e)}finally{Ye(),r()}}}const Ic={get(e,t){return me(e,"get",""),e[t]}};function po(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,Ic),slots:e.slots,emit:e.emit,expose:t}}function Ys(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(bi(bn(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Bt)return Bt[n](e)},has(t,n){return n in t||n in Bt}})):e.proxy}function Pc(e,t=!0){return G(e)?e.displayName||e.name:e.name||t&&e.__name}function Lc(e){return G(e)&&"__vccOpts"in e}const oe=(e,t)=>xl(e,t,en);function Ls(e,t,n){try{In(-1);const s=arguments.length;return s===2?te(t)&&!B(t)?Zt(t)?de(e,null,[t]):de(e,t):de(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Zt(n)&&(n=[n]),de(e,t,n))}finally{In(1)}}const Nc="3.5.27";/** +* @vue/runtime-dom v3.5.27 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Ns;const Sr=typeof window<"u"&&window.trustedTypes;if(Sr)try{Ns=Sr.createPolicy("vue",{createHTML:e=>e})}catch{}const go=Ns?e=>Ns.createHTML(e):e=>e,Fc="http://www.w3.org/2000/svg",Hc="http://www.w3.org/1998/Math/MathML",Ke=typeof document<"u"?document:null,xr=Ke&&Ke.createElement("template"),Dc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?Ke.createElementNS(Fc,e):t==="mathml"?Ke.createElementNS(Hc,e):n?Ke.createElement(e,{is:n}):Ke.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>Ke.createTextNode(e),createComment:e=>Ke.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ke.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const l=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{xr.innerHTML=go(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const o=xr.content;if(s==="svg"||s==="mathml"){const c=o.firstChild;for(;c.firstChild;)o.appendChild(c.firstChild);o.removeChild(c)}t.insertBefore(o,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},tt="transition",Vt="animation",tn=Symbol("_vtc"),mo={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},$c=fe({},Mi,mo),jc=e=>(e.displayName="Transition",e.props=$c,e),Cf=jc((e,{slots:t})=>Ls(Dl,Vc(e),t)),dt=(e,t=[])=>{B(e)?e.forEach(n=>n(...t)):e&&e(...t)},Tr=e=>e?B(e)?e.some(t=>t.length>1):e.length>1:!1;function Vc(e){const t={};for(const y in e)y in mo||(t[y]=e[y]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:o=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:u=l,appearToClass:a=o,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:v=`${n}-leave-active`,leaveToClass:_=`${n}-leave-to`}=e,C=Wc(r),P=C&&C[0],K=C&&C[1],{onBeforeEnter:H,onEnter:V,onEnterCancelled:p,onLeave:g,onLeaveCancelled:O,onBeforeAppear:W=H,onAppear:R=V,onAppearCancelled:U=p}=t,T=(y,N,Y,ie)=>{y._enterCancelled=ie,ht(y,N?a:o),ht(y,N?u:l),Y&&Y()},I=(y,N)=>{y._isLeaving=!1,ht(y,h),ht(y,_),ht(y,v),N&&N()},E=y=>(N,Y)=>{const ie=y?R:V,j=()=>T(N,y,Y);dt(ie,[N,j]),Er(()=>{ht(N,y?c:i),Be(N,y?a:o),Tr(ie)||Cr(N,s,P,j)})};return fe(t,{onBeforeEnter(y){dt(H,[y]),Be(y,i),Be(y,l)},onBeforeAppear(y){dt(W,[y]),Be(y,c),Be(y,u)},onEnter:E(!1),onAppear:E(!0),onLeave(y,N){y._isLeaving=!0;const Y=()=>I(y,N);Be(y,h),y._enterCancelled?(Be(y,v),Mr(y)):(Mr(y),Be(y,v)),Er(()=>{y._isLeaving&&(ht(y,h),Be(y,_),Tr(g)||Cr(y,s,K,Y))}),dt(g,[y,Y])},onEnterCancelled(y){T(y,!1,void 0,!0),dt(p,[y])},onAppearCancelled(y){T(y,!0,void 0,!0),dt(U,[y])},onLeaveCancelled(y){I(y),dt(O,[y])}})}function Wc(e){if(e==null)return null;if(te(e))return[cs(e.enter),cs(e.leave)];{const t=cs(e);return[t,t]}}function cs(e){return $o(e)}function Be(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[tn]||(e[tn]=new Set)).add(t)}function ht(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[tn];n&&(n.delete(t),n.size||(e[tn]=void 0))}function Er(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let kc=0;function Cr(e,t,n,s){const r=e._endId=++kc,i=()=>{r===e._endId&&s()};if(n!=null)return setTimeout(i,n);const{type:l,timeout:o,propCount:c}=Uc(e,t);if(!l)return s();const u=l+"end";let a=0;const h=()=>{e.removeEventListener(u,v),i()},v=_=>{_.target===e&&++a>=c&&h()};setTimeout(()=>{a(n[C]||"").split(", "),r=s(`${tt}Delay`),i=s(`${tt}Duration`),l=Ar(r,i),o=s(`${Vt}Delay`),c=s(`${Vt}Duration`),u=Ar(o,c);let a=null,h=0,v=0;t===tt?l>0&&(a=tt,h=l,v=i.length):t===Vt?u>0&&(a=Vt,h=u,v=c.length):(h=Math.max(l,u),a=h>0?l>u?tt:Vt:null,v=a?a===tt?i.length:c.length:0);const _=a===tt&&/\b(?:transform|all)(?:,|$)/.test(s(`${tt}Property`).toString());return{type:a,timeout:h,propCount:v,hasTransform:_}}function Ar(e,t){for(;e.lengthRr(n)+Rr(e[s])))}function Rr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function Mr(e){return(e?e.ownerDocument:document).body.offsetHeight}function Bc(e,t,n){const s=e[tn];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Or=Symbol("_vod"),Kc=Symbol("_vsh"),qc=Symbol(""),Gc=/(?:^|;)\s*display\s*:/;function Xc(e,t,n){const s=e.style,r=le(n);let i=!1;if(n&&!r){if(t)if(le(t))for(const l of t.split(";")){const o=l.slice(0,l.indexOf(":")).trim();n[o]==null&&Sn(s,o,"")}else for(const l in t)n[l]==null&&Sn(s,l,"");for(const l in n)l==="display"&&(i=!0),Sn(s,l,n[l])}else if(r){if(t!==n){const l=s[qc];l&&(n+=";"+l),s.cssText=n,i=Gc.test(n)}}else t&&e.removeAttribute("style");Or in e&&(e[Or]=i?s.display:"",e[Kc]&&(s.display="none"))}const Ir=/\s*!important$/;function Sn(e,t,n){if(B(n))n.forEach(s=>Sn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=Yc(e,t);Ir.test(n)?e.setProperty(at(s),n.replace(Ir,""),"important"):e[s]=n}}const Pr=["Webkit","Moz","ms"],as={};function Yc(e,t){const n=as[t];if(n)return n;let s=Le(t);if(s!=="filter"&&s in e)return as[t]=s;s=Hn(s);for(let r=0;rfs||(ea.then(()=>fs=0),fs=Date.now());function na(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;De(sa(s,n.value),t,5,[s])};return n.value=e,n.attached=ta(),n}function sa(e,t){if(B(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const $r=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,ra=(e,t,n,s,r,i)=>{const l=r==="svg";t==="class"?Bc(e,s,l):t==="style"?Xc(e,n,s):nn(t)?Hs(t)||Qc(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):ia(e,t,s,l))?(Fr(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Nr(e,t,s,l,i,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!le(s))?Fr(e,Le(t),s,i,t):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Nr(e,t,s,l))};function ia(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&$r(t)&&G(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return $r(t)&&le(n)?!1:t in e}const oa=["ctrl","shift","alt","meta"],la={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>oa.some(n=>e[`${n}Key`]&&!t.includes(n))},Af=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...i)=>{for(let l=0;l{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const i=at(r.key);if(t.some(l=>l===i||ca[l]===i))return e(r)})},aa=fe({patchProp:ra},Dc);let us,jr=!1;function fa(){return us=jr?us:_c(aa),jr=!0,us}const Mf=(...e)=>{const t=fa().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=da(s);if(r)return n(r,!0,ua(r))},t};function ua(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function da(e){return le(e)?document.querySelector(e):e}const ha=window.__VP_SITE_DATA__;function vo(e){return ri()?(Go(e),!0):!1}const ds=new WeakMap,pa=(...e)=>{var t;const n=e[0],s=(t=Et())==null?void 0:t.proxy;if(s==null&&!Ei())throw new Error("injectLocal must be called in setup");return s&&ds.has(s)&&n in ds.get(s)?ds.get(s)[n]:_t(...e)},yo=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const ga=Object.prototype.toString,ma=e=>ga.call(e)==="[object Object]",Tt=()=>{},Vr=va();function va(){var e,t;return yo&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function Js(e,t){function n(...s){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(i)})}return n}const _o=e=>e();function ya(e,t={}){let n,s,r=Tt;const i=c=>{clearTimeout(c),r(),r=Tt};let l;return c=>{const u=ce(e),a=ce(t.maxWait);return n&&i(n),u<=0||a!==void 0&&a<=0?(s&&(i(s),s=null),Promise.resolve(c())):new Promise((h,v)=>{r=t.rejectOnCancel?v:h,l=c,a&&!s&&(s=setTimeout(()=>{n&&i(n),s=null,h(l())},a)),n=setTimeout(()=>{s&&i(s),s=null,h(c())},u)})}}function _a(...e){let t=0,n,s=!0,r=Tt,i,l,o,c,u;!ae(e[0])&&typeof e[0]=="object"?{delay:l,trailing:o=!0,leading:c=!0,rejectOnCancel:u=!1}=e[0]:[l,o=!0,c=!0,u=!1]=e;const a=()=>{n&&(clearTimeout(n),n=void 0,r(),r=Tt)};return v=>{const _=ce(l),C=Date.now()-t,P=()=>i=v();return a(),_<=0?(t=Date.now(),P()):(C>_&&(c||!s)?(t=Date.now(),P()):o&&(i=new Promise((K,H)=>{r=u?H:K,n=setTimeout(()=>{t=Date.now(),s=!0,K(P()),a()},Math.max(0,_-C))})),!c&&!n&&(n=setTimeout(()=>s=!0,_)),s=!1,i)}}function ba(e=_o,t={}){const{initialState:n="active"}=t,s=zs(n==="active");function r(){s.value=!1}function i(){s.value=!0}return{isActive:Yt(s),pause:r,resume:i,eventFilter:(...o)=>{s.value&&e(...o)}}}function Wr(e){return e.endsWith("rem")?Number.parseFloat(e)*16:Number.parseFloat(e)}function wa(e){return Et()}function hs(e){return Array.isArray(e)?e:[e]}function zs(...e){if(e.length!==1)return bl(...e);const t=e[0];return typeof t=="function"?Yt(vl(()=>({get:t,set:Tt}))):yt(t)}function Sa(e,t=200,n={}){return Js(ya(t,n),e)}function xa(e,t=200,n=!1,s=!0,r=!1){return Js(_a(t,n,s,r),e)}function Ta(e,t,n={}){const{eventFilter:s=_o,...r}=n;return Pe(e,Js(s,t),r)}function Ea(e,t,n={}){const{eventFilter:s,initialState:r="active",...i}=n,{eventFilter:l,pause:o,resume:c,isActive:u}=ba(s,{initialState:r});return{stop:Ta(e,t,{...i,eventFilter:l}),pause:o,resume:c,isActive:u}}function Yn(e,t=!0,n){wa()?Ht(e,n):t?e():Un(e)}function Ca(e,t,n){return Pe(e,t,{...n,immediate:!0})}const ze=yo?window:void 0;function Qs(e){var t;const n=ce(e);return(t=n==null?void 0:n.$el)!=null?t:n}function Qe(...e){const t=[],n=()=>{t.forEach(o=>o()),t.length=0},s=(o,c,u,a)=>(o.addEventListener(c,u,a),()=>o.removeEventListener(c,u,a)),r=oe(()=>{const o=hs(ce(e[0])).filter(c=>c!=null);return o.every(c=>typeof c!="string")?o:void 0}),i=Ca(()=>{var o,c;return[(c=(o=r.value)==null?void 0:o.map(u=>Qs(u)))!=null?c:[ze].filter(u=>u!=null),hs(ce(r.value?e[1]:e[0])),hs(Wn(r.value?e[2]:e[1])),ce(r.value?e[3]:e[2])]},([o,c,u,a])=>{if(n(),!(o!=null&&o.length)||!(c!=null&&c.length)||!(u!=null&&u.length))return;const h=ma(a)?{...a}:a;t.push(...o.flatMap(v=>c.flatMap(_=>u.map(C=>s(v,_,C,h)))))},{flush:"post"}),l=()=>{i(),n()};return vo(n),l}function Aa(){const e=Ie(!1),t=Et();return t&&Ht(()=>{e.value=!0},t),e}function Ra(e){const t=Aa();return oe(()=>(t.value,!!e()))}function Ma(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function Of(...e){let t,n,s={};e.length===3?(t=e[0],n=e[1],s=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],s=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=ze,eventName:i="keydown",passive:l=!1,dedupe:o=!1}=s,c=Ma(t);return Qe(r,i,a=>{a.repeat&&ce(o)||c(a)&&n(a)},l)}const Oa=Symbol("vueuse-ssr-width");function Ia(){const e=Ei()?pa(Oa,null):null;return typeof e=="number"?e:void 0}function bo(e,t={}){const{window:n=ze,ssrWidth:s=Ia()}=t,r=Ra(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function"),i=Ie(typeof s=="number"),l=Ie(),o=Ie(!1),c=u=>{o.value=u.matches};return Ci(()=>{if(i.value){i.value=!r.value;const u=ce(e).split(",");o.value=u.some(a=>{const h=a.includes("not all"),v=a.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/),_=a.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);let C=!!(v||_);return v&&C&&(C=s>=Wr(v[1])),_&&C&&(C=s<=Wr(_[1])),h?!C:C});return}r.value&&(l.value=n.matchMedia(ce(e)),o.value=l.value.matches)}),Qe(l,"change",c,{passive:!0}),oe(()=>o.value)}const gn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},mn="__vueuse_ssr_handlers__",Pa=La();function La(){return mn in gn||(gn[mn]=gn[mn]||{}),gn[mn]}function wo(e,t){return Pa[e]||t}function So(e){return bo("(prefers-color-scheme: dark)",e)}function Na(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Fa={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},kr="vueuse-storage";function Ha(e,t,n,s={}){var r;const{flush:i="pre",deep:l=!0,listenToStorageChanges:o=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:a,window:h=ze,eventFilter:v,onError:_=E=>{console.error(E)},initOnMounted:C}=s,P=(a?Ie:yt)(typeof t=="function"?t():t),K=oe(()=>ce(e));if(!n)try{n=wo("getDefaultStorage",()=>{var E;return(E=ze)==null?void 0:E.localStorage})()}catch(E){_(E)}if(!n)return P;const H=ce(t),V=Na(H),p=(r=s.serializer)!=null?r:Fa[V],{pause:g,resume:O}=Ea(P,()=>R(P.value),{flush:i,deep:l,eventFilter:v});Pe(K,()=>T(),{flush:i}),h&&o&&Yn(()=>{n instanceof Storage?Qe(h,"storage",T,{passive:!0}):Qe(h,kr,I),C&&T()}),C||T();function W(E,y){if(h){const N={key:K.value,oldValue:E,newValue:y,storageArea:n};h.dispatchEvent(n instanceof Storage?new StorageEvent("storage",N):new CustomEvent(kr,{detail:N}))}}function R(E){try{const y=n.getItem(K.value);if(E==null)W(y,null),n.removeItem(K.value);else{const N=p.write(E);y!==N&&(n.setItem(K.value,N),W(y,N))}}catch(y){_(y)}}function U(E){const y=E?E.newValue:n.getItem(K.value);if(y==null)return c&&H!=null&&n.setItem(K.value,p.write(H)),H;if(!E&&u){const N=p.read(y);return typeof u=="function"?u(N,H):V==="object"&&!Array.isArray(N)?{...H,...N}:N}else return typeof y!="string"?y:p.read(y)}function T(E){if(!(E&&E.storageArea!==n)){if(E&&E.key==null){P.value=H;return}if(!(E&&E.key!==K.value)){g();try{(E==null?void 0:E.newValue)!==p.write(P.value)&&(P.value=U(E))}catch(y){_(y)}finally{E?Un(O):O()}}}}function I(E){T(E.detail)}return P}const Da="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";function $a(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:r=ze,storage:i,storageKey:l="vueuse-color-scheme",listenToStorageChanges:o=!0,storageRef:c,emitAuto:u,disableTransition:a=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},v=So({window:r}),_=oe(()=>v.value?"dark":"light"),C=c||(l==null?zs(s):Ha(l,s,i,{window:r,listenToStorageChanges:o})),P=oe(()=>C.value==="auto"?_.value:C.value),K=wo("updateHTMLAttrs",(g,O,W)=>{const R=typeof g=="string"?r==null?void 0:r.document.querySelector(g):Qs(g);if(!R)return;const U=new Set,T=new Set;let I=null;if(O==="class"){const y=W.split(/\s/g);Object.values(h).flatMap(N=>(N||"").split(/\s/g)).filter(Boolean).forEach(N=>{y.includes(N)?U.add(N):T.add(N)})}else I={key:O,value:W};if(U.size===0&&T.size===0&&I===null)return;let E;a&&(E=r.document.createElement("style"),E.appendChild(document.createTextNode(Da)),r.document.head.appendChild(E));for(const y of U)R.classList.add(y);for(const y of T)R.classList.remove(y);I&&R.setAttribute(I.key,I.value),a&&(r.getComputedStyle(E).opacity,document.head.removeChild(E))});function H(g){var O;K(t,n,(O=h[g])!=null?O:g)}function V(g){e.onChanged?e.onChanged(g,H):H(g)}Pe(P,V,{flush:"post",immediate:!0}),Yn(()=>V(P.value));const p=oe({get(){return u?C.value:P.value},set(g){C.value=g}});return Object.assign(p,{store:C,system:_,state:P})}function ja(e={}){const{valueDark:t="dark",valueLight:n=""}=e,s=$a({...e,onChanged:(l,o)=>{var c;e.onChanged?(c=e.onChanged)==null||c.call(e,l==="dark",o,l):o(l)},modes:{dark:t,light:n}}),r=oe(()=>s.system.value);return oe({get(){return s.value==="dark"},set(l){const o=l?"dark":"light";r.value===o?s.value="auto":s.value=o}})}function ps(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}const Ur=1;function Va(e,t={}){const{throttle:n=0,idle:s=200,onStop:r=Tt,onScroll:i=Tt,offset:l={left:0,right:0,top:0,bottom:0},eventListenerOptions:o={capture:!1,passive:!0},behavior:c="auto",window:u=ze,onError:a=R=>{console.error(R)}}=t,h=Ie(0),v=Ie(0),_=oe({get(){return h.value},set(R){P(R,void 0)}}),C=oe({get(){return v.value},set(R){P(void 0,R)}});function P(R,U){var T,I,E,y;if(!u)return;const N=ce(e);if(!N)return;(E=N instanceof Document?u.document.body:N)==null||E.scrollTo({top:(T=ce(U))!=null?T:C.value,left:(I=ce(R))!=null?I:_.value,behavior:ce(c)});const Y=((y=N==null?void 0:N.document)==null?void 0:y.documentElement)||(N==null?void 0:N.documentElement)||N;_!=null&&(h.value=Y.scrollLeft),C!=null&&(v.value=Y.scrollTop)}const K=Ie(!1),H=Nt({left:!0,right:!1,top:!0,bottom:!1}),V=Nt({left:!1,right:!1,top:!1,bottom:!1}),p=R=>{K.value&&(K.value=!1,V.left=!1,V.right=!1,V.top=!1,V.bottom=!1,r(R))},g=Sa(p,n+s),O=R=>{var U;if(!u)return;const T=((U=R==null?void 0:R.document)==null?void 0:U.documentElement)||(R==null?void 0:R.documentElement)||Qs(R),{display:I,flexDirection:E,direction:y}=getComputedStyle(T),N=y==="rtl"?-1:1,Y=T.scrollLeft;V.left=Yh.value;const ie=Math.abs(Y*N)<=(l.left||0),j=Math.abs(Y*N)+T.clientWidth>=T.scrollWidth-(l.right||0)-Ur;I==="flex"&&E==="row-reverse"?(H.left=j,H.right=ie):(H.left=ie,H.right=j),h.value=Y;let X=T.scrollTop;R===u.document&&!X&&(X=u.document.body.scrollTop),V.top=Xv.value;const D=Math.abs(X)<=(l.top||0),ee=Math.abs(X)+T.clientHeight>=T.scrollHeight-(l.bottom||0)-Ur;I==="flex"&&E==="column-reverse"?(H.top=ee,H.bottom=D):(H.top=D,H.bottom=ee),v.value=X},W=R=>{var U;if(!u)return;const T=(U=R.target.documentElement)!=null?U:R.target;O(T),K.value=!0,g(R),i(R)};return Qe(e,"scroll",n?xa(W,n,!0,!1):W,o),Yn(()=>{try{const R=ce(e);if(!R)return;O(R)}catch(R){a(R)}}),Qe(e,"scrollend",p,o),{x:_,y:C,isScrolling:K,arrivedState:H,directions:V,measure(){const R=ce(e);u&&R&&O(R)}}}function xo(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const gs=new WeakMap;function If(e,t=!1){const n=Ie(t);let s=null,r="";Pe(zs(e),o=>{const c=ps(ce(o));if(c){const u=c;if(gs.get(u)||gs.set(u,u.style.overflow),u.style.overflow!=="hidden"&&(r=u.style.overflow),u.style.overflow==="hidden")return n.value=!0;if(n.value)return u.style.overflow="hidden"}},{immediate:!0});const i=()=>{const o=ps(ce(e));!o||n.value||(Vr&&(s=Qe(o,"touchmove",c=>{Wa(c)},{passive:!1})),o.style.overflow="hidden",n.value=!0)},l=()=>{const o=ps(ce(e));!o||!n.value||(Vr&&(s==null||s()),o.style.overflow=r,gs.delete(o),n.value=!1)};return vo(l),oe({get(){return n.value},set(o){o?i():l()}})}function Pf(e={}){const{window:t=ze,...n}=e;return Va(t,n)}function Lf(e={}){const{window:t=ze,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,listenOrientation:r=!0,includeScrollbar:i=!0,type:l="inner"}=e,o=Ie(n),c=Ie(s),u=()=>{if(t)if(l==="outer")o.value=t.outerWidth,c.value=t.outerHeight;else if(l==="visual"&&t.visualViewport){const{width:h,height:v,scale:_}=t.visualViewport;o.value=Math.round(h*_),c.value=Math.round(v*_)}else i?(o.value=t.innerWidth,c.value=t.innerHeight):(o.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight)};u(),Yn(u);const a={passive:!0};if(Qe("resize",u,a),t&&l==="visual"&&t.visualViewport&&Qe(t.visualViewport,"resize",u,a),r){const h=bo("(orientation: portrait)");Pe(h,()=>u())}return{width:o,height:c}}const ms={};var vs={};const To=/^(?:[a-z]+:|\/\/)/i,ka="vitepress-theme-appearance",Ua=/#.*$/,Ba=/[?#].*$/,Ka=/(?:(^|\/)index)?\.(?:md|html)$/,ge=typeof document<"u",Eo={relativePath:"404.md",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function qa(e,t,n=!1){if(t===void 0)return!1;if(e=Br(`/${e}`),n)return new RegExp(t).test(e);if(Br(t)!==e)return!1;const s=t.match(Ua);return s?(ge?location.hash:"")===s[0]:!0}function Br(e){return decodeURI(e).replace(Ba,"").replace(Ka,"$1")}function Ga(e){return To.test(e)}function Xa(e,t){return Object.keys((e==null?void 0:e.locales)||{}).find(n=>n!=="root"&&!Ga(n)&&qa(t,`/${n}/`,!0))||"root"}function Ya(e,t){var s,r,i,l,o,c,u;const n=Xa(e,t);return Object.assign({},e,{localeIndex:n,lang:((s=e.locales[n])==null?void 0:s.lang)??e.lang,dir:((r=e.locales[n])==null?void 0:r.dir)??e.dir,title:((i=e.locales[n])==null?void 0:i.title)??e.title,titleTemplate:((l=e.locales[n])==null?void 0:l.titleTemplate)??e.titleTemplate,description:((o=e.locales[n])==null?void 0:o.description)??e.description,head:Ao(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(u=e.locales[n])==null?void 0:u.themeConfig}})}function Co(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const r=Ja(e.title,s);return n===r.slice(3)?n:`${n}${r}`}function Ja(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function za(e,t){const[n,s]=t;if(n!=="meta")return!1;const r=Object.entries(s)[0];return r==null?!1:e.some(([i,l])=>i===n&&l[r[0]]===r[1])}function Ao(e,t){return[...e.filter(n=>!za(t,n)),...t]}const Qa=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,Za=/^[a-z]:/i;function Kr(e){const t=Za.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(Qa,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const ys=new Set;function ef(e){if(ys.size===0){const n=typeof process=="object"&&(vs==null?void 0:vs.VITE_EXTRA_EXTENSIONS)||(ms==null?void 0:ms.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(s=>ys.add(s))}const t=e.split(".").pop();return t==null||!ys.has(t.toLowerCase())}const tf=Symbol(),xt=Ie(ha);function Nf(e){const t=oe(()=>Ya(xt.value,e.data.relativePath)),n=t.value.appearance,s=n==="force-dark"?yt(!0):n==="force-auto"?So():n?ja({storageKey:ka,initialValue:()=>n==="dark"?"dark":"auto",...typeof n=="object"?n:{}}):yt(!1),r=yt(ge?location.hash:"");return ge&&window.addEventListener("hashchange",()=>{r.value=location.hash}),Pe(()=>e.data,()=>{r.value=ge?location.hash:""}),{site:t,theme:oe(()=>t.value.themeConfig),page:oe(()=>e.data),frontmatter:oe(()=>e.data.frontmatter),params:oe(()=>e.data.params),lang:oe(()=>t.value.lang),dir:oe(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:oe(()=>t.value.localeIndex||"root"),title:oe(()=>Co(t.value,e.data)),description:oe(()=>e.data.description||t.value.description),isDark:s,hash:oe(()=>r.value)}}function nf(){const e=_t(tf);if(!e)throw new Error("vitepress data not properly injected in app");return e}function sf(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function qr(e){return To.test(e)||!e.startsWith("/")?e:sf(xt.value.base,e)}function rf(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),ge){const n="/";t=Kr(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];if(s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),!s)return null;t=`${n}assets/${t}.${s}.js`}else t=`./${Kr(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let xn=[];function Ff(e){xn.push(e),Gn(()=>{xn=xn.filter(t=>t!==e)})}function of(){let e=xt.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=Gr(e,n);else if(Array.isArray(e))for(const s of e){const r=Gr(s,n);if(r){t=r;break}}return t}function Gr(e,t){const n=document.querySelector(e);if(!n)return 0;const s=n.getBoundingClientRect().bottom;return s<0?0:s+t}const lf=Symbol(),Ro="http://a.com",cf=()=>({path:"/",component:null,data:Eo});function Hf(e,t){const n=Nt(cf()),s={route:n,go:r};async function r(o=ge?location.href:"/"){var c,u;o=_s(o),await((c=s.onBeforeRouteChange)==null?void 0:c.call(s,o))!==!1&&(ge&&o!==_s(location.href)&&(history.replaceState({scrollPosition:window.scrollY},""),history.pushState({},"",o)),await l(o),await((u=s.onAfterRouteChange??s.onAfterRouteChanged)==null?void 0:u(o)))}let i=null;async function l(o,c=0,u=!1){var v,_;if(await((v=s.onBeforePageLoad)==null?void 0:v.call(s,o))===!1)return;const a=new URL(o,Ro),h=i=a.pathname;try{let C=await e(h);if(!C)throw new Error(`Page not found: ${h}`);if(i===h){i=null;const{default:P,__pageData:K}=C;if(!P)throw new Error(`Invalid route component: ${P}`);await((_=s.onAfterPageLoad)==null?void 0:_.call(s,o)),n.path=ge?h:qr(h),n.component=bn(P),n.data=bn(K),ge&&Un(()=>{let H=xt.value.base+K.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!xt.value.cleanUrls&&!H.endsWith("/")&&(H+=".html"),H!==a.pathname&&(a.pathname=H,o=H+a.search+a.hash,history.replaceState({},"",o)),a.hash&&!c){let V=null;try{V=document.getElementById(decodeURIComponent(a.hash).slice(1))}catch(p){console.warn(p)}if(V){Xr(V,a.hash);return}}window.scrollTo(0,c)})}}catch(C){if(!/fetch|Page not found/.test(C.message)&&!/^\/404(\.html|\/)?$/.test(o)&&console.error(C),!u)try{const P=await fetch(xt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await P.json(),await l(o,c,!0);return}catch{}if(i===h){i=null,n.path=ge?h:qr(h),n.component=t?bn(t):null;const P=ge?h.replace(/(^|\/)$/,"$1index").replace(/(\.html)?$/,".md").replace(/^\//,""):"404.md";n.data={...Eo,relativePath:P}}}}return ge&&(history.state===null&&history.replaceState({},""),window.addEventListener("click",o=>{if(o.defaultPrevented||!(o.target instanceof Element)||o.target.closest("button")||o.button!==0||o.ctrlKey||o.shiftKey||o.altKey||o.metaKey)return;const c=o.target.closest("a");if(!c||c.closest(".vp-raw")||c.hasAttribute("download")||c.hasAttribute("target"))return;const u=c.getAttribute("href")??(c instanceof SVGAElement?c.getAttribute("xlink:href"):null);if(u==null)return;const{href:a,origin:h,pathname:v,hash:_,search:C}=new URL(u,c.baseURI),P=new URL(location.href);h===P.origin&&ef(v)&&(o.preventDefault(),v===P.pathname&&C===P.search?(_!==P.hash&&(history.pushState({},"",a),window.dispatchEvent(new HashChangeEvent("hashchange",{oldURL:P.href,newURL:a}))),_?Xr(c,_,c.classList.contains("header-anchor")):window.scrollTo(0,0)):r(a))},{capture:!0}),window.addEventListener("popstate",async o=>{var u;if(o.state===null)return;const c=_s(location.href);await l(c,o.state&&o.state.scrollPosition||0),await((u=s.onAfterRouteChange??s.onAfterRouteChanged)==null?void 0:u(c))}),window.addEventListener("hashchange",o=>{o.preventDefault()})),s}function af(){const e=_t(lf);if(!e)throw new Error("useRouter() is called without provider.");return e}function Mo(){return af().route}function Xr(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(r){console.warn(r)}if(s){let r=function(){!n||Math.abs(l-window.scrollY)>window.innerHeight?window.scrollTo(0,l):window.scrollTo({left:0,top:l,behavior:"smooth"})};const i=parseInt(window.getComputedStyle(s).paddingTop,10),l=window.scrollY+s.getBoundingClientRect().top-of()+i;requestAnimationFrame(r)}}function _s(e){const t=new URL(e,Ro);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),xt.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const vn=()=>xn.forEach(e=>e()),Df=Ni({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=Mo(),{frontmatter:n,site:s}=nf();return Pe(n,vn,{deep:!0,flush:"post"}),()=>Ls(e.as,s.value.contentProps??{style:{position:"relative"}},[t.component?Ls(t.component,{onVnodeMounted:vn,onVnodeUpdated:vn,onVnodeUnmounted:vn}):"404 Page Not Found"])}}),$f=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},jf=Ni({setup(e,{slots:t}){const n=yt(!1);return Ht(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function Vf(){ge&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const s=(n=t.parentElement)==null?void 0:n.parentElement;if(!s)return;const r=Array.from(s.querySelectorAll("input")).indexOf(t);if(r<0)return;const i=s.querySelector(".blocks");if(!i)return;const l=Array.from(i.children).find(u=>u.classList.contains("active"));if(!l)return;const o=i.children[r];if(!o||l===o)return;l.classList.remove("active"),o.classList.add("active");const c=s==null?void 0:s.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function Wf(){if(ge){const e=new WeakMap;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,i=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!r||!i)return;const l=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className),o=[".vp-copy-ignore",".diff.remove"],c=i.cloneNode(!0);c.querySelectorAll(o.join(",")).forEach(a=>a.remove());let u=c.textContent||"";l&&(u=u.replace(/^ *(\$|>) /gm,"").trim()),ff(u).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const a=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,a)})}})}}async function ff(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),r=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),r&&(s.removeAllRanges(),s.addRange(r)),n&&n.focus()}}function kf(e,t){let n=!0,s=[];const r=i=>{if(n){n=!1,i.forEach(o=>{const c=bs(o);for(const u of document.head.children)if(u.isEqualNode(c)){s.push(u);return}});return}const l=i.map(bs);s.forEach((o,c)=>{const u=l.findIndex(a=>a==null?void 0:a.isEqualNode(o??null));u!==-1?delete l[u]:(o==null||o.remove(),delete s[c])}),l.forEach(o=>o&&document.head.appendChild(o)),s=[...s,...l].filter(Boolean)};Ci(()=>{const i=e.data,l=t.value,o=i&&i.description,c=i&&i.frontmatter.head||[],u=Co(l,i);u!==document.title&&(document.title=u);const a=o||l.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==a&&h.setAttribute("content",a):bs(["meta",{name:"description",content:a}]),r(Ao(l.head,df(c)))})}function bs([e,t,n]){const s=document.createElement(e);for(const r in t)s.setAttribute(r,t[r]);return n&&(s.innerHTML=n),e==="script"&&t.async==null&&(s.async=!1),s}function uf(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function df(e){return e.filter(t=>!uf(t))}const ws=new Set,Oo=()=>document.createElement("link"),hf=e=>{const t=Oo();t.rel="prefetch",t.href=e,document.head.appendChild(t)},pf=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let yn;const gf=ge&&(yn=Oo())&&yn.relList&&yn.relList.supports&&yn.relList.supports("prefetch")?hf:pf;function Uf(){if(!ge||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(l=>{if(l.isIntersecting){const o=l.target;n.unobserve(o);const{pathname:c}=o;if(!ws.has(c)){ws.add(c);const u=rf(c);u&&gf(u)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{hostname:l,pathname:o}=new URL(i.href instanceof SVGAnimatedString?i.href.animVal:i.href,i.baseURI),c=o.match(/\.\w+$/);c&&c[0]!==".html"||i.target!=="_blank"&&l===location.hostname&&(o!==location.pathname?n.observe(i):ws.add(o))})})};Ht(s);const r=Mo();Pe(()=>r.path,s),Gn(()=>{n&&n.disconnect()})}export{Sf as $,of as A,_f as B,vf as C,Ff as D,Ie as E,ve as F,de as G,yf as H,To as I,Mo as J,Ec as K,_t as L,Lf as M,$s as N,Of as O,Un as P,Pf as Q,ge as R,Yt as S,Cf as T,If as U,Ol as V,wf as W,Rf as X,Di as Y,Af as Z,$f as _,fo as a,kf as a0,lf as a1,Nf as a2,tf as a3,Df as a4,jf as a5,xt as a6,Hf as a7,rf as a8,Mf as a9,Uf as aa,Wf as ab,Vf as ac,Ls as ad,Tf as ae,Is as b,xf as c,Ni as d,Ef as e,ef as f,qr as g,oe as h,Ga as i,ao as j,Wn as k,qa as l,bo as m,js as n,Os as o,yt as p,Pe as q,bf as r,Ci as s,Ko as t,nf as u,Ht as v,Ml as w,Gn as x,mf as y,Gl as z}; diff --git a/docs/.vitepress/dist/assets/chunks/theme.Bte6VuTq.js b/docs/.vitepress/dist/assets/chunks/theme.Bte6VuTq.js new file mode 100644 index 0000000..d4f5369 --- /dev/null +++ b/docs/.vitepress/dist/assets/chunks/theme.Bte6VuTq.js @@ -0,0 +1 @@ +import{d as p,c as u,r as c,n as T,o as s,a as j,t as N,b as _,w as h,T as ce,e as m,_ as b,u as He,i as Ae,f as Be,g as ue,h as g,j as v,k as i,l as z,m as se,p as S,q as F,s as Y,v as U,x as de,y as ve,z as Ce,A as Ee,F as x,B as H,C as W,D as Q,E as ge,G as k,H as C,I as $e,J as X,K as G,L as Z,M as Fe,N as ye,O as De,P as Pe,Q as Le,R as ee,S as Oe,U as Ve,V as Se,W as Ge,X as Ue,Y as je,Z as ze,$ as We}from"./framework.DvGhUH3j.js";const qe=p({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(e){return(t,n)=>(s(),u("span",{class:T(["VPBadge",e.type])},[c(t.$slots,"default",{},()=>[j(N(e.text),1)])],2))}}),Ke={key:0,class:"VPBackdrop"},Re=p({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(e){return(t,n)=>(s(),_(ce,{name:"fade"},{default:h(()=>[e.show?(s(),u("div",Ke)):m("",!0)]),_:1}))}}),Je=b(Re,[["__scopeId","data-v-c79a1216"]]),P=He;function Ye(e,t){let n,a=!1;return()=>{n&&clearTimeout(n),a?n=setTimeout(e,t):(e(),(a=!0)&&setTimeout(()=>a=!1,t))}}function ie(e){return e.startsWith("/")?e:`/${e}`}function fe(e){const{pathname:t,search:n,hash:a,protocol:o}=new URL(e,"http://a.com");if(Ae(e)||e.startsWith("#")||!o.startsWith("http")||!Be(t))return e;const{site:r}=P(),l=t.endsWith("/")||t.endsWith(".html")?e:e.replace(/(?:(^\.+)\/)?.*$/,`$1${t.replace(/(\.md)?$/,r.value.cleanUrls?"":".html")}${n}${a}`);return ue(l)}function K({correspondingLink:e=!1}={}){const{site:t,localeIndex:n,page:a,theme:o,hash:r}=P(),l=g(()=>{var d,y;return{label:(d=t.value.locales[n.value])==null?void 0:d.label,link:((y=t.value.locales[n.value])==null?void 0:y.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:g(()=>Object.entries(t.value.locales).flatMap(([d,y])=>l.value.label===y.label?[]:{text:y.label,link:Qe(y.link||(d==="root"?"/":`/${d}/`),o.value.i18nRouting!==!1&&e,a.value.relativePath.slice(l.value.link.length-1),!t.value.cleanUrls)+r.value})),currentLang:l}}function Qe(e,t,n,a){return t?e.replace(/\/$/,"")+ie(n.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,a?".html":"")):e}const Xe={class:"NotFound"},Ze={class:"code"},et={class:"title"},tt={class:"quote"},nt={class:"action"},at=["href","aria-label"],ot=p({__name:"NotFound",setup(e){const{theme:t}=P(),{currentLang:n}=K();return(a,o)=>{var r,l,f,d,y;return s(),u("div",Xe,[v("p",Ze,N(((r=i(t).notFound)==null?void 0:r.code)??"404"),1),v("h1",et,N(((l=i(t).notFound)==null?void 0:l.title)??"PAGE NOT FOUND"),1),o[0]||(o[0]=v("div",{class:"divider"},null,-1)),v("blockquote",tt,N(((f=i(t).notFound)==null?void 0:f.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),v("div",nt,[v("a",{class:"link",href:i(ue)(i(n).link),"aria-label":((d=i(t).notFound)==null?void 0:d.linkLabel)??"go to home"},N(((y=i(t).notFound)==null?void 0:y.linkText)??"Take me home"),9,at)])])}}}),st=b(ot,[["__scopeId","data-v-d6be1790"]]);function Te(e,t){if(Array.isArray(e))return R(e);if(e==null)return[];t=ie(t);const n=Object.keys(e).sort((o,r)=>r.split("/").length-o.split("/").length).find(o=>t.startsWith(ie(o))),a=n?e[n]:[];return Array.isArray(a)?R(a):R(a.items,a.base)}function it(e){const t=[];let n=0;for(const a in e){const o=e[a];if(o.items){n=t.push(o);continue}t[n]||t.push({items:[]}),t[n].items.push(o)}return t}function rt(e){const t=[];function n(a){for(const o of a)o.text&&o.link&&t.push({text:o.text,link:o.link,docFooterText:o.docFooterText}),o.items&&n(o.items)}return n(e),t}function re(e,t){return Array.isArray(t)?t.some(n=>re(e,n)):z(e,t.link)?!0:t.items?re(e,t.items):!1}function R(e,t){return[...e].map(n=>{const a={...n},o=a.base||t;return o&&a.link&&(a.link=o+a.link),a.items&&(a.items=R(a.items,o)),a})}function D(){const{frontmatter:e,page:t,theme:n}=P(),a=se("(min-width: 960px)"),o=S(!1),r=g(()=>{const w=n.value.sidebar,A=t.value.relativePath;return w?Te(w,A):[]}),l=S(r.value);F(r,(w,A)=>{JSON.stringify(w)!==JSON.stringify(A)&&(l.value=r.value)});const f=g(()=>e.value.sidebar!==!1&&l.value.length>0&&e.value.layout!=="home"),d=g(()=>y?e.value.aside==null?n.value.aside==="left":e.value.aside==="left":!1),y=g(()=>e.value.layout==="home"?!1:e.value.aside!=null?!!e.value.aside:n.value.aside!==!1),L=g(()=>f.value&&a.value),$=g(()=>f.value?it(l.value):[]);function V(){o.value=!0}function M(){o.value=!1}function I(){o.value?M():V()}return{isOpen:o,sidebar:l,sidebarGroups:$,hasSidebar:f,hasAside:y,leftAside:d,isSidebarEnabled:L,open:V,close:M,toggle:I}}function lt(e,t){let n;Y(()=>{n=e.value?document.activeElement:void 0}),U(()=>{window.addEventListener("keyup",a)}),de(()=>{window.removeEventListener("keyup",a)});function a(o){o.key==="Escape"&&e.value&&(t(),n==null||n.focus())}}function ct(e){const{page:t,hash:n}=P(),a=S(!1),o=g(()=>e.value.collapsed!=null),r=g(()=>!!e.value.link),l=S(!1),f=()=>{l.value=z(t.value.relativePath,e.value.link)};F([t,e,n],f),U(f);const d=g(()=>l.value?!0:e.value.items?re(t.value.relativePath,e.value.items):!1),y=g(()=>!!(e.value.items&&e.value.items.length));Y(()=>{a.value=!!(o.value&&e.value.collapsed)}),ve(()=>{(l.value||d.value)&&(a.value=!1)});function L(){o.value&&(a.value=!a.value)}return{collapsed:a,collapsible:o,isLink:r,isActiveLink:l,hasActiveLink:d,hasChildren:y,toggle:L}}function ut(){const{hasSidebar:e}=D(),t=se("(min-width: 960px)"),n=se("(min-width: 1280px)");return{isAsideEnabled:g(()=>!n.value&&!t.value?!1:e.value?n.value:t.value)}}const dt=/\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/,le=[];function Ne(e){return typeof e.outline=="object"&&!Array.isArray(e.outline)&&e.outline.label||e.outlineTitle||"On this page"}function he(e){const t=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(n=>n.id&&n.hasChildNodes()).map(n=>{const a=Number(n.tagName[1]);return{element:n,title:vt(n),link:"#"+n.id,level:a}});return ft(t,e)}function vt(e){let t="";for(const n of e.childNodes)if(n.nodeType===1){if(dt.test(n.className))continue;t+=n.textContent}else n.nodeType===3&&(t+=n.textContent);return t.trim()}function ft(e,t){if(t===!1)return[];const n=(typeof t=="object"&&!Array.isArray(t)?t.level:t)||2,[a,o]=typeof n=="number"?[n,n]:n==="deep"?[2,6]:n;return pt(e,a,o)}function ht(e,t){const{isAsideEnabled:n}=ut(),a=Ye(r,100);let o=null;U(()=>{requestAnimationFrame(r),window.addEventListener("scroll",a)}),Ce(()=>{l(location.hash)}),de(()=>{window.removeEventListener("scroll",a)});function r(){if(!n.value)return;const f=window.scrollY,d=window.innerHeight,y=document.body.offsetHeight,L=Math.abs(f+d-y)<1,$=le.map(({element:M,link:I})=>({link:I,top:mt(M)})).filter(({top:M})=>!Number.isNaN(M)).sort((M,I)=>M.top-I.top);if(!$.length){l(null);return}if(f<1){l(null);return}if(L){l($[$.length-1].link);return}let V=null;for(const{link:M,top:I}of $){if(I>f+Ee()+4)break;V=M}l(V)}function l(f){o&&o.classList.remove("active"),f==null?o=null:o=e.value.querySelector(`a[href="${decodeURIComponent(f)}"]`);const d=o;d?(d.classList.add("active"),t.value.style.top=d.offsetTop+39+"px",t.value.style.opacity="1"):(t.value.style.top="33px",t.value.style.opacity="0")}}function mt(e){let t=0;for(;e!==document.body;){if(e===null)return NaN;t+=e.offsetTop,e=e.offsetParent}return t}function pt(e,t,n){le.length=0;const a=[],o=[];return e.forEach(r=>{const l={...r,children:[]};let f=o[o.length-1];for(;f&&f.level>=l.level;)o.pop(),f=o[o.length-1];if(l.element.classList.contains("ignore-header")||f&&"shouldIgnore"in f){o.push({level:l.level,shouldIgnore:!0});return}l.level>n||l.level{const o=W("VPDocOutlineItem",!0);return s(),u("ul",{class:T(["VPDocOutlineItem",e.root?"root":"nested"])},[(s(!0),u(x,null,H(e.headers,({children:r,link:l,title:f})=>(s(),u("li",null,[v("a",{class:"outline-link",href:l,onClick:t,title:f},N(f),9,kt),r!=null&&r.length?(s(),_(o,{key:0,headers:r},null,8,["headers"])):m("",!0)]))),256))],2)}}}),Me=b(_t,[["__scopeId","data-v-b933a997"]]),bt={class:"content"},gt={"aria-level":"2",class:"outline-title",id:"doc-outline-aria-label",role:"heading"},$t=p({__name:"VPDocAsideOutline",setup(e){const{frontmatter:t,theme:n}=P(),a=ge([]);Q(()=>{a.value=he(t.value.outline??n.value.outline)});const o=S(),r=S();return ht(o,r),(l,f)=>(s(),u("nav",{"aria-labelledby":"doc-outline-aria-label",class:T(["VPDocAsideOutline",{"has-outline":a.value.length>0}]),ref_key:"container",ref:o},[v("div",bt,[v("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),v("div",gt,N(i(Ne)(i(n))),1),k(Me,{headers:a.value,root:!0},null,8,["headers"])])],2))}}),yt=b($t,[["__scopeId","data-v-a5bbad30"]]),Pt={class:"VPDocAsideCarbonAds"},Lt=p({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(e){const t=()=>null;return(n,a)=>(s(),u("div",Pt,[k(i(t),{"carbon-ads":e.carbonAds},null,8,["carbon-ads"])]))}}),Vt={class:"VPDocAside"},St=p({__name:"VPDocAside",setup(e){const{theme:t}=P();return(n,a)=>(s(),u("div",Vt,[c(n.$slots,"aside-top",{},void 0,!0),c(n.$slots,"aside-outline-before",{},void 0,!0),k(yt),c(n.$slots,"aside-outline-after",{},void 0,!0),a[0]||(a[0]=v("div",{class:"spacer"},null,-1)),c(n.$slots,"aside-ads-before",{},void 0,!0),i(t).carbonAds?(s(),_(Lt,{key:0,"carbon-ads":i(t).carbonAds},null,8,["carbon-ads"])):m("",!0),c(n.$slots,"aside-ads-after",{},void 0,!0),c(n.$slots,"aside-bottom",{},void 0,!0)]))}}),Tt=b(St,[["__scopeId","data-v-3f215769"]]);function Nt(){const{theme:e,page:t}=P();return g(()=>{const{text:n="Edit this page",pattern:a=""}=e.value.editLink||{};let o;return typeof a=="function"?o=a(t.value):o=a.replace(/:path/g,t.value.filePath),{url:o,text:n}})}function Mt(){const{page:e,theme:t,frontmatter:n}=P();return g(()=>{var y,L,$,V,M,I,w,A;const a=Te(t.value.sidebar,e.value.relativePath),o=rt(a),r=xt(o,B=>B.link.replace(/[?#].*$/,"")),l=r.findIndex(B=>z(e.value.relativePath,B.link)),f=((y=t.value.docFooter)==null?void 0:y.prev)===!1&&!n.value.prev||n.value.prev===!1,d=((L=t.value.docFooter)==null?void 0:L.next)===!1&&!n.value.next||n.value.next===!1;return{prev:f?void 0:{text:(typeof n.value.prev=="string"?n.value.prev:typeof n.value.prev=="object"?n.value.prev.text:void 0)??(($=r[l-1])==null?void 0:$.docFooterText)??((V=r[l-1])==null?void 0:V.text),link:(typeof n.value.prev=="object"?n.value.prev.link:void 0)??((M=r[l-1])==null?void 0:M.link)},next:d?void 0:{text:(typeof n.value.next=="string"?n.value.next:typeof n.value.next=="object"?n.value.next.text:void 0)??((I=r[l+1])==null?void 0:I.docFooterText)??((w=r[l+1])==null?void 0:w.text),link:(typeof n.value.next=="object"?n.value.next.link:void 0)??((A=r[l+1])==null?void 0:A.link)}}})}function xt(e,t){const n=new Set;return e.filter(a=>{const o=t(a);return n.has(o)?!1:n.add(o)})}const E=p({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(e){const t=e,n=g(()=>t.tag??(t.href?"a":"span")),a=g(()=>t.href&&$e.test(t.href)||t.target==="_blank");return(o,r)=>(s(),_(C(n.value),{class:T(["VPLink",{link:e.href,"vp-external-link-icon":a.value,"no-icon":e.noIcon}]),href:e.href?i(fe)(e.href):void 0,target:e.target??(a.value?"_blank":void 0),rel:e.rel??(a.value?"noreferrer":void 0)},{default:h(()=>[c(o.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),It={class:"VPLastUpdated"},wt=["datetime"],Ht=p({__name:"VPDocFooterLastUpdated",setup(e){const{theme:t,page:n,lang:a}=P(),o=g(()=>new Date(n.value.lastUpdated)),r=g(()=>o.value.toISOString()),l=S("");return U(()=>{Y(()=>{var f,d,y;l.value=new Intl.DateTimeFormat((d=(f=t.value.lastUpdated)==null?void 0:f.formatOptions)!=null&&d.forceLocale?a.value:void 0,((y=t.value.lastUpdated)==null?void 0:y.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(o.value)})}),(f,d)=>{var y;return s(),u("p",It,[j(N(((y=i(t).lastUpdated)==null?void 0:y.text)||i(t).lastUpdatedText||"Last updated")+": ",1),v("time",{datetime:r.value},N(l.value),9,wt)])}}}),At=b(Ht,[["__scopeId","data-v-e98dd255"]]),Bt={key:0,class:"VPDocFooter"},Ct={key:0,class:"edit-info"},Et={key:0,class:"edit-link"},Ft={key:1,class:"last-updated"},Dt={key:1,class:"prev-next","aria-labelledby":"doc-footer-aria-label"},Ot={class:"pager"},Gt=["innerHTML"],Ut=["innerHTML"],jt={class:"pager"},zt=["innerHTML"],Wt=["innerHTML"],qt=p({__name:"VPDocFooter",setup(e){const{theme:t,page:n,frontmatter:a}=P(),o=Nt(),r=Mt(),l=g(()=>t.value.editLink&&a.value.editLink!==!1),f=g(()=>n.value.lastUpdated),d=g(()=>l.value||f.value||r.value.prev||r.value.next);return(y,L)=>{var $,V,M,I;return d.value?(s(),u("footer",Bt,[c(y.$slots,"doc-footer-before",{},void 0,!0),l.value||f.value?(s(),u("div",Ct,[l.value?(s(),u("div",Et,[k(E,{class:"edit-link-button",href:i(o).url,"no-icon":!0},{default:h(()=>[L[0]||(L[0]=v("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),j(" "+N(i(o).text),1)]),_:1},8,["href"])])):m("",!0),f.value?(s(),u("div",Ft,[k(At)])):m("",!0)])):m("",!0),($=i(r).prev)!=null&&$.link||(V=i(r).next)!=null&&V.link?(s(),u("nav",Dt,[L[1]||(L[1]=v("span",{class:"visually-hidden",id:"doc-footer-aria-label"},"Pager",-1)),v("div",Ot,[(M=i(r).prev)!=null&&M.link?(s(),_(E,{key:0,class:"pager-link prev",href:i(r).prev.link},{default:h(()=>{var w;return[v("span",{class:"desc",innerHTML:((w=i(t).docFooter)==null?void 0:w.prev)||"Previous page"},null,8,Gt),v("span",{class:"title",innerHTML:i(r).prev.text},null,8,Ut)]}),_:1},8,["href"])):m("",!0)]),v("div",jt,[(I=i(r).next)!=null&&I.link?(s(),_(E,{key:0,class:"pager-link next",href:i(r).next.link},{default:h(()=>{var w;return[v("span",{class:"desc",innerHTML:((w=i(t).docFooter)==null?void 0:w.next)||"Next page"},null,8,zt),v("span",{class:"title",innerHTML:i(r).next.text},null,8,Wt)]}),_:1},8,["href"])):m("",!0)])])):m("",!0)])):m("",!0)}}}),Kt=b(qt,[["__scopeId","data-v-e257564d"]]),Rt={class:"container"},Jt={class:"aside-container"},Yt={class:"aside-content"},Qt={class:"content"},Xt={class:"content-container"},Zt={class:"main"},en=p({__name:"VPDoc",setup(e){const{theme:t}=P(),n=X(),{hasSidebar:a,hasAside:o,leftAside:r}=D(),l=g(()=>n.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(f,d)=>{const y=W("Content");return s(),u("div",{class:T(["VPDoc",{"has-sidebar":i(a),"has-aside":i(o)}])},[c(f.$slots,"doc-top",{},void 0,!0),v("div",Rt,[i(o)?(s(),u("div",{key:0,class:T(["aside",{"left-aside":i(r)}])},[d[0]||(d[0]=v("div",{class:"aside-curtain"},null,-1)),v("div",Jt,[v("div",Yt,[k(Tt,null,{"aside-top":h(()=>[c(f.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":h(()=>[c(f.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":h(()=>[c(f.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":h(()=>[c(f.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":h(()=>[c(f.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":h(()=>[c(f.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):m("",!0),v("div",Qt,[v("div",Xt,[c(f.$slots,"doc-before",{},void 0,!0),v("main",Zt,[k(y,{class:T(["vp-doc",[l.value,i(t).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),k(Kt,null,{"doc-footer-before":h(()=>[c(f.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),c(f.$slots,"doc-after",{},void 0,!0)])])]),c(f.$slots,"doc-bottom",{},void 0,!0)],2)}}}),tn=b(en,[["__scopeId","data-v-39a288b8"]]),nn=p({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(e){const t=e,n=g(()=>t.href&&$e.test(t.href)),a=g(()=>t.tag||(t.href?"a":"button"));return(o,r)=>(s(),_(C(a.value),{class:T(["VPButton",[e.size,e.theme]]),href:e.href?i(fe)(e.href):void 0,target:t.target??(n.value?"_blank":void 0),rel:t.rel??(n.value?"noreferrer":void 0)},{default:h(()=>[j(N(e.text),1)]),_:1},8,["class","href","target","rel"]))}}),an=b(nn,[["__scopeId","data-v-fa7799d5"]]),on=["src","alt"],sn=p({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(e){return(t,n)=>{const a=W("VPImage",!0);return e.image?(s(),u(x,{key:0},[typeof e.image=="string"||"src"in e.image?(s(),u("img",G({key:0,class:"VPImage"},typeof e.image=="string"?t.$attrs:{...e.image,...t.$attrs},{src:i(ue)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,on)):(s(),u(x,{key:1},[k(a,G({class:"dark",image:e.image.dark,alt:e.image.alt},t.$attrs),null,16,["image","alt"]),k(a,G({class:"light",image:e.image.light,alt:e.image.alt},t.$attrs),null,16,["image","alt"])],64))],64)):m("",!0)}}}),J=b(sn,[["__scopeId","data-v-8426fc1a"]]),rn={class:"container"},ln={class:"main"},cn={class:"heading"},un=["innerHTML"],dn=["innerHTML"],vn=["innerHTML"],fn={key:0,class:"actions"},hn={key:0,class:"image"},mn={class:"image-container"},pn=p({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(e){const t=Z("hero-image-slot-exists");return(n,a)=>(s(),u("div",{class:T(["VPHero",{"has-image":e.image||i(t)}])},[v("div",rn,[v("div",ln,[c(n.$slots,"home-hero-info-before",{},void 0,!0),c(n.$slots,"home-hero-info",{},()=>[v("h1",cn,[e.name?(s(),u("span",{key:0,innerHTML:e.name,class:"name clip"},null,8,un)):m("",!0),e.text?(s(),u("span",{key:1,innerHTML:e.text,class:"text"},null,8,dn)):m("",!0)]),e.tagline?(s(),u("p",{key:0,innerHTML:e.tagline,class:"tagline"},null,8,vn)):m("",!0)],!0),c(n.$slots,"home-hero-info-after",{},void 0,!0),e.actions?(s(),u("div",fn,[(s(!0),u(x,null,H(e.actions,o=>(s(),u("div",{key:o.link,class:"action"},[k(an,{tag:"a",size:"medium",theme:o.theme,text:o.text,href:o.link,target:o.target,rel:o.rel},null,8,["theme","text","href","target","rel"])]))),128))])):m("",!0),c(n.$slots,"home-hero-actions-after",{},void 0,!0)]),e.image||i(t)?(s(),u("div",hn,[v("div",mn,[a[0]||(a[0]=v("div",{class:"image-bg"},null,-1)),c(n.$slots,"home-hero-image",{},()=>[e.image?(s(),_(J,{key:0,class:"image-src",image:e.image},null,8,["image"])):m("",!0)],!0)])])):m("",!0)])],2))}}),kn=b(pn,[["__scopeId","data-v-4f9c455b"]]),_n=p({__name:"VPHomeHero",setup(e){const{frontmatter:t}=P();return(n,a)=>i(t).hero?(s(),_(kn,{key:0,class:"VPHomeHero",name:i(t).hero.name,text:i(t).hero.text,tagline:i(t).hero.tagline,image:i(t).hero.image,actions:i(t).hero.actions},{"home-hero-info-before":h(()=>[c(n.$slots,"home-hero-info-before")]),"home-hero-info":h(()=>[c(n.$slots,"home-hero-info")]),"home-hero-info-after":h(()=>[c(n.$slots,"home-hero-info-after")]),"home-hero-actions-after":h(()=>[c(n.$slots,"home-hero-actions-after")]),"home-hero-image":h(()=>[c(n.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):m("",!0)}}),bn={class:"box"},gn={key:0,class:"icon"},$n=["innerHTML"],yn=["innerHTML"],Pn=["innerHTML"],Ln={key:4,class:"link-text"},Vn={class:"link-text-value"},Sn=p({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(e){return(t,n)=>(s(),_(E,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:h(()=>[v("article",bn,[typeof e.icon=="object"&&e.icon.wrap?(s(),u("div",gn,[k(J,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(s(),_(J,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(s(),u("div",{key:2,class:"icon",innerHTML:e.icon},null,8,$n)):m("",!0),v("h2",{class:"title",innerHTML:e.title},null,8,yn),e.details?(s(),u("p",{key:3,class:"details",innerHTML:e.details},null,8,Pn)):m("",!0),e.linkText?(s(),u("div",Ln,[v("p",Vn,[j(N(e.linkText)+" ",1),n[0]||(n[0]=v("span",{class:"vpi-arrow-right link-text-icon"},null,-1))])])):m("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),Tn=b(Sn,[["__scopeId","data-v-a3976bdc"]]),Nn={key:0,class:"VPFeatures"},Mn={class:"container"},xn={class:"items"},In=p({__name:"VPFeatures",props:{features:{}},setup(e){const t=e,n=g(()=>{const a=t.features.length;if(a){if(a===2)return"grid-2";if(a===3)return"grid-3";if(a%3===0)return"grid-6";if(a>3)return"grid-4"}else return});return(a,o)=>e.features?(s(),u("div",Nn,[v("div",Mn,[v("div",xn,[(s(!0),u(x,null,H(e.features,r=>(s(),u("div",{key:r.title,class:T(["item",[n.value]])},[k(Tn,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):m("",!0)}}),wn=b(In,[["__scopeId","data-v-a6181336"]]),Hn=p({__name:"VPHomeFeatures",setup(e){const{frontmatter:t}=P();return(n,a)=>i(t).features?(s(),_(wn,{key:0,class:"VPHomeFeatures",features:i(t).features},null,8,["features"])):m("",!0)}}),An=p({__name:"VPHomeContent",setup(e){const{width:t}=Fe({initialWidth:0,includeScrollbar:!1});return(n,a)=>(s(),u("div",{class:"vp-doc container",style:ye(i(t)?{"--vp-offset":`calc(50% - ${i(t)/2}px)`}:{})},[c(n.$slots,"default",{},void 0,!0)],4))}}),Bn=b(An,[["__scopeId","data-v-8e2d4988"]]),Cn=p({__name:"VPHome",setup(e){const{frontmatter:t,theme:n}=P();return(a,o)=>{const r=W("Content");return s(),u("div",{class:T(["VPHome",{"external-link-icon-enabled":i(n).externalLinkIcon}])},[c(a.$slots,"home-hero-before",{},void 0,!0),k(_n,null,{"home-hero-info-before":h(()=>[c(a.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":h(()=>[c(a.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":h(()=>[c(a.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":h(()=>[c(a.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":h(()=>[c(a.$slots,"home-hero-image",{},void 0,!0)]),_:3}),c(a.$slots,"home-hero-after",{},void 0,!0),c(a.$slots,"home-features-before",{},void 0,!0),k(Hn),c(a.$slots,"home-features-after",{},void 0,!0),i(t).markdownStyles!==!1?(s(),_(Bn,{key:0},{default:h(()=>[k(r)]),_:1})):(s(),_(r,{key:1}))],2)}}}),En=b(Cn,[["__scopeId","data-v-8b561e3d"]]),Fn={},Dn={class:"VPPage"};function On(e,t){const n=W("Content");return s(),u("div",Dn,[c(e.$slots,"page-top"),k(n),c(e.$slots,"page-bottom")])}const Gn=b(Fn,[["render",On]]),Un=p({__name:"VPContent",setup(e){const{page:t,frontmatter:n}=P(),{hasSidebar:a}=D();return(o,r)=>(s(),u("div",{class:T(["VPContent",{"has-sidebar":i(a),"is-home":i(n).layout==="home"}]),id:"VPContent"},[i(t).isNotFound?c(o.$slots,"not-found",{key:0},()=>[k(st)],!0):i(n).layout==="page"?(s(),_(Gn,{key:1},{"page-top":h(()=>[c(o.$slots,"page-top",{},void 0,!0)]),"page-bottom":h(()=>[c(o.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(n).layout==="home"?(s(),_(En,{key:2},{"home-hero-before":h(()=>[c(o.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":h(()=>[c(o.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":h(()=>[c(o.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":h(()=>[c(o.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":h(()=>[c(o.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":h(()=>[c(o.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":h(()=>[c(o.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":h(()=>[c(o.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":h(()=>[c(o.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(n).layout&&i(n).layout!=="doc"?(s(),_(C(i(n).layout),{key:3})):(s(),_(tn,{key:4},{"doc-top":h(()=>[c(o.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":h(()=>[c(o.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":h(()=>[c(o.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":h(()=>[c(o.$slots,"doc-before",{},void 0,!0)]),"doc-after":h(()=>[c(o.$slots,"doc-after",{},void 0,!0)]),"aside-top":h(()=>[c(o.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":h(()=>[c(o.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":h(()=>[c(o.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":h(()=>[c(o.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":h(()=>[c(o.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":h(()=>[c(o.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),jn=b(Un,[["__scopeId","data-v-1428d186"]]),zn={class:"container"},Wn=["innerHTML"],qn=["innerHTML"],Kn=p({__name:"VPFooter",setup(e){const{theme:t,frontmatter:n}=P(),{hasSidebar:a}=D();return(o,r)=>i(t).footer&&i(n).footer!==!1?(s(),u("footer",{key:0,class:T(["VPFooter",{"has-sidebar":i(a)}])},[v("div",zn,[i(t).footer.message?(s(),u("p",{key:0,class:"message",innerHTML:i(t).footer.message},null,8,Wn)):m("",!0),i(t).footer.copyright?(s(),u("p",{key:1,class:"copyright",innerHTML:i(t).footer.copyright},null,8,qn)):m("",!0)])],2)):m("",!0)}}),Rn=b(Kn,[["__scopeId","data-v-e315a0ad"]]);function Jn(){const{theme:e,frontmatter:t}=P(),n=ge([]),a=g(()=>n.value.length>0);return Q(()=>{n.value=he(t.value.outline??e.value.outline)}),{headers:n,hasLocalNav:a}}const Yn={class:"menu-text"},Qn={class:"header"},Xn={class:"outline"},Zn=p({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(e){const t=e,{theme:n}=P(),a=S(!1),o=S(0),r=S(),l=S();function f($){var V;(V=r.value)!=null&&V.contains($.target)||(a.value=!1)}F(a,$=>{if($){document.addEventListener("click",f);return}document.removeEventListener("click",f)}),De("Escape",()=>{a.value=!1}),Q(()=>{a.value=!1});function d(){a.value=!a.value,o.value=window.innerHeight+Math.min(window.scrollY-t.navHeight,0)}function y($){$.target.classList.contains("outline-link")&&(l.value&&(l.value.style.transition="none"),Pe(()=>{a.value=!1}))}function L(){a.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return($,V)=>(s(),u("div",{class:"VPLocalNavOutlineDropdown",style:ye({"--vp-vh":o.value+"px"}),ref_key:"main",ref:r},[e.headers.length>0?(s(),u("button",{key:0,onClick:d,class:T({open:a.value})},[v("span",Yn,N(i(Ne)(i(n))),1),V[0]||(V[0]=v("span",{class:"vpi-chevron-right icon"},null,-1))],2)):(s(),u("button",{key:1,onClick:L},N(i(n).returnToTopLabel||"Return to top"),1)),k(ce,{name:"flyout"},{default:h(()=>[a.value?(s(),u("div",{key:0,ref_key:"items",ref:l,class:"items",onClick:y},[v("div",Qn,[v("a",{class:"top-link",href:"#",onClick:L},N(i(n).returnToTopLabel||"Return to top"),1)]),v("div",Xn,[k(Me,{headers:e.headers},null,8,["headers"])])],512)):m("",!0)]),_:1})],4))}}),ea=b(Zn,[["__scopeId","data-v-8a42e2b4"]]),ta={class:"container"},na=["aria-expanded"],aa={class:"menu-text"},oa=p({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(e){const{theme:t,frontmatter:n}=P(),{hasSidebar:a}=D(),{headers:o}=Jn(),{y:r}=Le(),l=S(0);U(()=>{l.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Q(()=>{o.value=he(n.value.outline??t.value.outline)});const f=g(()=>o.value.length===0),d=g(()=>f.value&&!a.value),y=g(()=>({VPLocalNav:!0,"has-sidebar":a.value,empty:f.value,fixed:d.value}));return(L,$)=>i(n).layout!=="home"&&(!d.value||i(r)>=l.value)?(s(),u("div",{key:0,class:T(y.value)},[v("div",ta,[i(a)?(s(),u("button",{key:0,class:"menu","aria-expanded":e.open,"aria-controls":"VPSidebarNav",onClick:$[0]||($[0]=V=>L.$emit("open-menu"))},[$[1]||($[1]=v("span",{class:"vpi-align-left menu-icon"},null,-1)),v("span",aa,N(i(t).sidebarMenuLabel||"Menu"),1)],8,na)):m("",!0),k(ea,{headers:i(o),navHeight:l.value},null,8,["headers","navHeight"])])],2)):m("",!0)}}),sa=b(oa,[["__scopeId","data-v-a6f0e41e"]]);function ia(){const e=S(!1);function t(){e.value=!0,window.addEventListener("resize",o)}function n(){e.value=!1,window.removeEventListener("resize",o)}function a(){e.value?n():t()}function o(){window.outerWidth>=768&&n()}const r=X();return F(()=>r.path,n),{isScreenOpen:e,openScreen:t,closeScreen:n,toggleScreen:a}}const ra={},la={class:"VPSwitch",type:"button",role:"switch"},ca={class:"check"},ua={key:0,class:"icon"};function da(e,t){return s(),u("button",la,[v("span",ca,[e.$slots.default?(s(),u("span",ua,[c(e.$slots,"default",{},void 0,!0)])):m("",!0)])])}const va=b(ra,[["render",da],["__scopeId","data-v-1d5665e3"]]),fa=p({__name:"VPSwitchAppearance",setup(e){const{isDark:t,theme:n}=P(),a=Z("toggle-appearance",()=>{t.value=!t.value}),o=S("");return ve(()=>{o.value=t.value?n.value.lightModeSwitchTitle||"Switch to light theme":n.value.darkModeSwitchTitle||"Switch to dark theme"}),(r,l)=>(s(),_(va,{title:o.value,class:"VPSwitchAppearance","aria-checked":i(t),onClick:i(a)},{default:h(()=>[...l[0]||(l[0]=[v("span",{class:"vpi-sun sun"},null,-1),v("span",{class:"vpi-moon moon"},null,-1)])]),_:1},8,["title","aria-checked","onClick"]))}}),me=b(fa,[["__scopeId","data-v-5337faa4"]]),ha={key:0,class:"VPNavBarAppearance"},ma=p({__name:"VPNavBarAppearance",setup(e){const{site:t}=P();return(n,a)=>i(t).appearance&&i(t).appearance!=="force-dark"&&i(t).appearance!=="force-auto"?(s(),u("div",ha,[k(me)])):m("",!0)}}),pa=b(ma,[["__scopeId","data-v-6c893767"]]),pe=S();let xe=!1,oe=0;function ka(e){const t=S(!1);if(ee){!xe&&_a(),oe++;const n=F(pe,a=>{var o,r,l;a===e.el.value||(o=e.el.value)!=null&&o.contains(a)?(t.value=!0,(r=e.onFocus)==null||r.call(e)):(t.value=!1,(l=e.onBlur)==null||l.call(e))});de(()=>{n(),oe--,oe||ba()})}return Oe(t)}function _a(){document.addEventListener("focusin",Ie),xe=!0,pe.value=document.activeElement}function ba(){document.removeEventListener("focusin",Ie)}function Ie(){pe.value=document.activeElement}const ga={class:"VPMenuLink"},$a=["innerHTML"],ya=p({__name:"VPMenuLink",props:{item:{}},setup(e){const{page:t}=P();return(n,a)=>(s(),u("div",ga,[k(E,{class:T({active:i(z)(i(t).relativePath,e.item.activeMatch||e.item.link,!!e.item.activeMatch)}),href:e.item.link,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon},{default:h(()=>[v("span",{innerHTML:e.item.text},null,8,$a)]),_:1},8,["class","href","target","rel","no-icon"])]))}}),te=b(ya,[["__scopeId","data-v-35975db6"]]),Pa={class:"VPMenuGroup"},La={key:0,class:"title"},Va=p({__name:"VPMenuGroup",props:{text:{},items:{}},setup(e){return(t,n)=>(s(),u("div",Pa,[e.text?(s(),u("p",La,N(e.text),1)):m("",!0),(s(!0),u(x,null,H(e.items,a=>(s(),u(x,null,["link"in a?(s(),_(te,{key:0,item:a},null,8,["item"])):m("",!0)],64))),256))]))}}),Sa=b(Va,[["__scopeId","data-v-69e747b5"]]),Ta={class:"VPMenu"},Na={key:0,class:"items"},Ma=p({__name:"VPMenu",props:{items:{}},setup(e){return(t,n)=>(s(),u("div",Ta,[e.items?(s(),u("div",Na,[(s(!0),u(x,null,H(e.items,a=>(s(),u(x,{key:JSON.stringify(a)},["link"in a?(s(),_(te,{key:0,item:a},null,8,["item"])):"component"in a?(s(),_(C(a.component),G({key:1,ref_for:!0},a.props),null,16)):(s(),_(Sa,{key:2,text:a.text,items:a.items},null,8,["text","items"]))],64))),128))])):m("",!0),c(t.$slots,"default",{},void 0,!0)]))}}),xa=b(Ma,[["__scopeId","data-v-b98bc113"]]),Ia=["aria-expanded","aria-label"],wa={key:0,class:"text"},Ha=["innerHTML"],Aa={key:1,class:"vpi-more-horizontal icon"},Ba={class:"menu"},Ca=p({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(e){const t=S(!1),n=S();ka({el:n,onBlur:a});function a(){t.value=!1}return(o,r)=>(s(),u("div",{class:"VPFlyout",ref_key:"el",ref:n,onMouseenter:r[1]||(r[1]=l=>t.value=!0),onMouseleave:r[2]||(r[2]=l=>t.value=!1)},[v("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":t.value,"aria-label":e.label,onClick:r[0]||(r[0]=l=>t.value=!t.value)},[e.button||e.icon?(s(),u("span",wa,[e.icon?(s(),u("span",{key:0,class:T([e.icon,"option-icon"])},null,2)):m("",!0),e.button?(s(),u("span",{key:1,innerHTML:e.button},null,8,Ha)):m("",!0),r[3]||(r[3]=v("span",{class:"vpi-chevron-down text-icon"},null,-1))])):(s(),u("span",Aa))],8,Ia),v("div",Ba,[k(xa,{items:e.items},{default:h(()=>[c(o.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),ke=b(Ca,[["__scopeId","data-v-cf11d7a2"]]),Ea=["href","aria-label","innerHTML"],Fa=p({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(e){const t=e,n=S();U(async()=>{var r;await Pe();const o=(r=n.value)==null?void 0:r.children[0];o instanceof HTMLElement&&o.className.startsWith("vpi-social-")&&(getComputedStyle(o).maskImage||getComputedStyle(o).webkitMaskImage)==="none"&&o.style.setProperty("--icon",`url('https://api.iconify.design/simple-icons/${t.icon}.svg')`)});const a=g(()=>typeof t.icon=="object"?t.icon.svg:``);return(o,r)=>(s(),u("a",{ref_key:"el",ref:n,class:"VPSocialLink no-icon",href:e.link,"aria-label":e.ariaLabel??(typeof e.icon=="string"?e.icon:""),target:"_blank",rel:"noopener",innerHTML:a.value},null,8,Ea))}}),Da=b(Fa,[["__scopeId","data-v-bd121fe5"]]),Oa={class:"VPSocialLinks"},Ga=p({__name:"VPSocialLinks",props:{links:{}},setup(e){return(t,n)=>(s(),u("div",Oa,[(s(!0),u(x,null,H(e.links,({link:a,icon:o,ariaLabel:r})=>(s(),_(Da,{key:a,icon:o,link:a,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}}),_e=b(Ga,[["__scopeId","data-v-7bc22406"]]),Ua={key:0,class:"group translations"},ja={class:"trans-title"},za={key:1,class:"group"},Wa={class:"item appearance"},qa={class:"label"},Ka={class:"appearance-action"},Ra={key:2,class:"group"},Ja={class:"item social-links"},Ya=p({__name:"VPNavBarExtra",setup(e){const{site:t,theme:n}=P(),{localeLinks:a,currentLang:o}=K({correspondingLink:!0}),r=g(()=>a.value.length&&o.value.label||t.value.appearance||n.value.socialLinks);return(l,f)=>r.value?(s(),_(ke,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:h(()=>[i(a).length&&i(o).label?(s(),u("div",Ua,[v("p",ja,N(i(o).label),1),(s(!0),u(x,null,H(i(a),d=>(s(),_(te,{key:d.link,item:d},null,8,["item"]))),128))])):m("",!0),i(t).appearance&&i(t).appearance!=="force-dark"&&i(t).appearance!=="force-auto"?(s(),u("div",za,[v("div",Wa,[v("p",qa,N(i(n).darkModeSwitchLabel||"Appearance"),1),v("div",Ka,[k(me)])])])):m("",!0),i(n).socialLinks?(s(),u("div",Ra,[v("div",Ja,[k(_e,{class:"social-links-list",links:i(n).socialLinks},null,8,["links"])])])):m("",!0)]),_:1})):m("",!0)}}),Qa=b(Ya,[["__scopeId","data-v-bb2aa2f0"]]),Xa=["aria-expanded"],Za=p({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(e){return(t,n)=>(s(),u("button",{type:"button",class:T(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:n[0]||(n[0]=a=>t.$emit("click"))},[...n[1]||(n[1]=[v("span",{class:"container"},[v("span",{class:"top"}),v("span",{class:"middle"}),v("span",{class:"bottom"})],-1)])],10,Xa))}}),eo=b(Za,[["__scopeId","data-v-e5dd9c1c"]]),to=["innerHTML"],no=p({__name:"VPNavBarMenuLink",props:{item:{}},setup(e){const{page:t}=P();return(n,a)=>(s(),_(E,{class:T({VPNavBarMenuLink:!0,active:i(z)(i(t).relativePath,e.item.activeMatch||e.item.link,!!e.item.activeMatch)}),href:e.item.link,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,tabindex:"0"},{default:h(()=>[v("span",{innerHTML:e.item.text},null,8,to)]),_:1},8,["class","href","target","rel","no-icon"]))}}),ao=b(no,[["__scopeId","data-v-e56f3d57"]]),oo=p({__name:"VPNavBarMenuGroup",props:{item:{}},setup(e){const t=e,{page:n}=P(),a=r=>"component"in r?!1:"link"in r?z(n.value.relativePath,r.link,!!t.item.activeMatch):r.items.some(a),o=g(()=>a(t.item));return(r,l)=>(s(),_(ke,{class:T({VPNavBarMenuGroup:!0,active:i(z)(i(n).relativePath,e.item.activeMatch,!!e.item.activeMatch)||o.value}),button:e.item.text,items:e.item.items},null,8,["class","button","items"]))}}),so={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},io=p({__name:"VPNavBarMenu",setup(e){const{theme:t}=P();return(n,a)=>i(t).nav?(s(),u("nav",so,[a[0]||(a[0]=v("span",{id:"main-nav-aria-label",class:"visually-hidden"}," Main Navigation ",-1)),(s(!0),u(x,null,H(i(t).nav,o=>(s(),u(x,{key:JSON.stringify(o)},["link"in o?(s(),_(ao,{key:0,item:o},null,8,["item"])):"component"in o?(s(),_(C(o.component),G({key:1,ref_for:!0},o.props),null,16)):(s(),_(oo,{key:2,item:o},null,8,["item"]))],64))),128))])):m("",!0)}}),ro=b(io,[["__scopeId","data-v-dc692963"]]);function lo(e){const{localeIndex:t,theme:n}=P();function a(o){var I,w,A;const r=o.split("."),l=(I=n.value.search)==null?void 0:I.options,f=l&&typeof l=="object",d=f&&((A=(w=l.locales)==null?void 0:w[t.value])==null?void 0:A.translations)||null,y=f&&l.translations||null;let L=d,$=y,V=e;const M=r.pop();for(const B of r){let O=null;const q=V==null?void 0:V[B];q&&(O=V=q);const ne=$==null?void 0:$[B];ne&&(O=$=ne);const ae=L==null?void 0:L[B];ae&&(O=L=ae),q||(V=O),ne||($=O),ae||(L=O)}return(L==null?void 0:L[M])??($==null?void 0:$[M])??(V==null?void 0:V[M])??""}return a}const co=["aria-label"],uo={class:"DocSearch-Button-Container"},vo={class:"DocSearch-Button-Placeholder"},be=p({__name:"VPNavBarSearchButton",setup(e){const n=lo({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(a,o)=>(s(),u("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":i(n)("button.buttonAriaLabel")},[v("span",uo,[o[0]||(o[0]=v("span",{class:"vp-icon DocSearch-Search-Icon"},null,-1)),v("span",vo,N(i(n)("button.buttonText")),1)]),o[1]||(o[1]=v("span",{class:"DocSearch-Button-Keys"},[v("kbd",{class:"DocSearch-Button-Key"}),v("kbd",{class:"DocSearch-Button-Key"},"K")],-1))],8,co))}}),fo={class:"VPNavBarSearch"},ho={id:"local-search"},mo={key:1,id:"docsearch"},po=p({__name:"VPNavBarSearch",setup(e){const t=()=>null,n=()=>null,{theme:a}=P(),o=S(!1),r=S(!1);U(()=>{});function l(){o.value||(o.value=!0,setTimeout(f,16))}function f(){const L=new Event("keydown");L.key="k",L.metaKey=!0,window.dispatchEvent(L),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||f()},16)}const d=S(!1),y="";return(L,$)=>{var V;return s(),u("div",fo,[i(y)==="local"?(s(),u(x,{key:0},[d.value?(s(),_(i(t),{key:0,onClose:$[0]||($[0]=M=>d.value=!1)})):m("",!0),v("div",ho,[k(be,{onClick:$[1]||($[1]=M=>d.value=!0)})])],64)):i(y)==="algolia"?(s(),u(x,{key:1},[o.value?(s(),_(i(n),{key:0,algolia:((V=i(a).search)==null?void 0:V.options)??i(a).algolia,onVnodeBeforeMount:$[2]||($[2]=M=>r.value=!0)},null,8,["algolia"])):m("",!0),r.value?m("",!0):(s(),u("div",mo,[k(be,{onClick:l})]))],64)):m("",!0)])}}}),ko=p({__name:"VPNavBarSocialLinks",setup(e){const{theme:t}=P();return(n,a)=>i(t).socialLinks?(s(),_(_e,{key:0,class:"VPNavBarSocialLinks",links:i(t).socialLinks},null,8,["links"])):m("",!0)}}),_o=b(ko,[["__scopeId","data-v-0394ad82"]]),bo=["href","rel","target"],go=["innerHTML"],$o={key:2},yo=p({__name:"VPNavBarTitle",setup(e){const{site:t,theme:n}=P(),{hasSidebar:a}=D(),{currentLang:o}=K(),r=g(()=>{var d;return typeof n.value.logoLink=="string"?n.value.logoLink:(d=n.value.logoLink)==null?void 0:d.link}),l=g(()=>{var d;return typeof n.value.logoLink=="string"||(d=n.value.logoLink)==null?void 0:d.rel}),f=g(()=>{var d;return typeof n.value.logoLink=="string"||(d=n.value.logoLink)==null?void 0:d.target});return(d,y)=>(s(),u("div",{class:T(["VPNavBarTitle",{"has-sidebar":i(a)}])},[v("a",{class:"title",href:r.value??i(fe)(i(o).link),rel:l.value,target:f.value},[c(d.$slots,"nav-bar-title-before",{},void 0,!0),i(n).logo?(s(),_(J,{key:0,class:"logo",image:i(n).logo},null,8,["image"])):m("",!0),i(n).siteTitle?(s(),u("span",{key:1,innerHTML:i(n).siteTitle},null,8,go)):i(n).siteTitle===void 0?(s(),u("span",$o,N(i(t).title),1)):m("",!0),c(d.$slots,"nav-bar-title-after",{},void 0,!0)],8,bo)],2))}}),Po=b(yo,[["__scopeId","data-v-1168a8e4"]]),Lo={class:"items"},Vo={class:"title"},So=p({__name:"VPNavBarTranslations",setup(e){const{theme:t}=P(),{localeLinks:n,currentLang:a}=K({correspondingLink:!0});return(o,r)=>i(n).length&&i(a).label?(s(),_(ke,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:i(t).langMenuLabel||"Change language"},{default:h(()=>[v("div",Lo,[v("p",Vo,N(i(a).label),1),(s(!0),u(x,null,H(i(n),l=>(s(),_(te,{key:l.link,item:l},null,8,["item"]))),128))])]),_:1},8,["label"])):m("",!0)}}),To=b(So,[["__scopeId","data-v-88af2de4"]]),No={class:"wrapper"},Mo={class:"container"},xo={class:"title"},Io={class:"content"},wo={class:"content-body"},Ho=p({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(e){const t=e,{y:n}=Le(),{hasSidebar:a}=D(),{frontmatter:o}=P(),r=S({});return ve(()=>{r.value={"has-sidebar":a.value,home:o.value.layout==="home",top:n.value===0,"screen-open":t.isScreenOpen}}),(l,f)=>(s(),u("div",{class:T(["VPNavBar",r.value])},[v("div",No,[v("div",Mo,[v("div",xo,[k(Po,null,{"nav-bar-title-before":h(()=>[c(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":h(()=>[c(l.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),v("div",Io,[v("div",wo,[c(l.$slots,"nav-bar-content-before",{},void 0,!0),k(po,{class:"search"}),k(ro,{class:"menu"}),k(To,{class:"translations"}),k(pa,{class:"appearance"}),k(_o,{class:"social-links"}),k(Qa,{class:"extra"}),c(l.$slots,"nav-bar-content-after",{},void 0,!0),k(eo,{class:"hamburger",active:e.isScreenOpen,onClick:f[0]||(f[0]=d=>l.$emit("toggle-screen"))},null,8,["active"])])])])]),f[1]||(f[1]=v("div",{class:"divider"},[v("div",{class:"divider-line"})],-1))],2))}}),Ao=b(Ho,[["__scopeId","data-v-6aa21345"]]),Bo={key:0,class:"VPNavScreenAppearance"},Co={class:"text"},Eo=p({__name:"VPNavScreenAppearance",setup(e){const{site:t,theme:n}=P();return(a,o)=>i(t).appearance&&i(t).appearance!=="force-dark"&&i(t).appearance!=="force-auto"?(s(),u("div",Bo,[v("p",Co,N(i(n).darkModeSwitchLabel||"Appearance"),1),k(me)])):m("",!0)}}),Fo=b(Eo,[["__scopeId","data-v-b44890b2"]]),Do=["innerHTML"],Oo=p({__name:"VPNavScreenMenuLink",props:{item:{}},setup(e){const t=Z("close-screen");return(n,a)=>(s(),_(E,{class:"VPNavScreenMenuLink",href:e.item.link,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,onClick:i(t)},{default:h(()=>[v("span",{innerHTML:e.item.text},null,8,Do)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),Go=b(Oo,[["__scopeId","data-v-df37e6dd"]]),Uo=["innerHTML"],jo=p({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(e){const t=Z("close-screen");return(n,a)=>(s(),_(E,{class:"VPNavScreenMenuGroupLink",href:e.item.link,target:e.item.target,rel:e.item.rel,"no-icon":e.item.noIcon,onClick:i(t)},{default:h(()=>[v("span",{innerHTML:e.item.text},null,8,Uo)]),_:1},8,["href","target","rel","no-icon","onClick"]))}}),we=b(jo,[["__scopeId","data-v-3e9c20e4"]]),zo={class:"VPNavScreenMenuGroupSection"},Wo={key:0,class:"title"},qo=p({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(e){return(t,n)=>(s(),u("div",zo,[e.text?(s(),u("p",Wo,N(e.text),1)):m("",!0),(s(!0),u(x,null,H(e.items,a=>(s(),_(we,{key:a.text,item:a},null,8,["item"]))),128))]))}}),Ko=b(qo,[["__scopeId","data-v-8133b170"]]),Ro=["aria-controls","aria-expanded"],Jo=["innerHTML"],Yo=["id"],Qo={key:0,class:"item"},Xo={key:1,class:"item"},Zo={key:2,class:"group"},es=p({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(e){const t=e,n=S(!1),a=g(()=>`NavScreenGroup-${t.text.replace(" ","-").toLowerCase()}`);function o(){n.value=!n.value}return(r,l)=>(s(),u("div",{class:T(["VPNavScreenMenuGroup",{open:n.value}])},[v("button",{class:"button","aria-controls":a.value,"aria-expanded":n.value,onClick:o},[v("span",{class:"button-text",innerHTML:e.text},null,8,Jo),l[0]||(l[0]=v("span",{class:"vpi-plus button-icon"},null,-1))],8,Ro),v("div",{id:a.value,class:"items"},[(s(!0),u(x,null,H(e.items,f=>(s(),u(x,{key:JSON.stringify(f)},["link"in f?(s(),u("div",Qo,[k(we,{item:f},null,8,["item"])])):"component"in f?(s(),u("div",Xo,[(s(),_(C(f.component),G({ref_for:!0},f.props,{"screen-menu":""}),null,16))])):(s(),u("div",Zo,[k(Ko,{text:f.text,items:f.items},null,8,["text","items"])]))],64))),128))],8,Yo)],2))}}),ts=b(es,[["__scopeId","data-v-b9ab8c58"]]),ns={key:0,class:"VPNavScreenMenu"},as=p({__name:"VPNavScreenMenu",setup(e){const{theme:t}=P();return(n,a)=>i(t).nav?(s(),u("nav",ns,[(s(!0),u(x,null,H(i(t).nav,o=>(s(),u(x,{key:JSON.stringify(o)},["link"in o?(s(),_(Go,{key:0,item:o},null,8,["item"])):"component"in o?(s(),_(C(o.component),G({key:1,ref_for:!0},o.props,{"screen-menu":""}),null,16)):(s(),_(ts,{key:2,text:o.text||"",items:o.items},null,8,["text","items"]))],64))),128))])):m("",!0)}}),os=p({__name:"VPNavScreenSocialLinks",setup(e){const{theme:t}=P();return(n,a)=>i(t).socialLinks?(s(),_(_e,{key:0,class:"VPNavScreenSocialLinks",links:i(t).socialLinks},null,8,["links"])):m("",!0)}}),ss={class:"list"},is=p({__name:"VPNavScreenTranslations",setup(e){const{localeLinks:t,currentLang:n}=K({correspondingLink:!0}),a=S(!1);function o(){a.value=!a.value}return(r,l)=>i(t).length&&i(n).label?(s(),u("div",{key:0,class:T(["VPNavScreenTranslations",{open:a.value}])},[v("button",{class:"title",onClick:o},[l[0]||(l[0]=v("span",{class:"vpi-languages icon lang"},null,-1)),j(" "+N(i(n).label)+" ",1),l[1]||(l[1]=v("span",{class:"vpi-chevron-down icon chevron"},null,-1))]),v("ul",ss,[(s(!0),u(x,null,H(i(t),f=>(s(),u("li",{key:f.link,class:"item"},[k(E,{class:"link",href:f.link},{default:h(()=>[j(N(f.text),1)]),_:2},1032,["href"])]))),128))])],2)):m("",!0)}}),rs=b(is,[["__scopeId","data-v-858fe1a4"]]),ls={class:"container"},cs=p({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(e){const t=S(null),n=Ve(ee?document.body:null);return(a,o)=>(s(),_(ce,{name:"fade",onEnter:o[0]||(o[0]=r=>n.value=!0),onAfterLeave:o[1]||(o[1]=r=>n.value=!1)},{default:h(()=>[e.open?(s(),u("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:t,id:"VPNavScreen"},[v("div",ls,[c(a.$slots,"nav-screen-content-before",{},void 0,!0),k(as,{class:"menu"}),k(rs,{class:"translations"}),k(Fo,{class:"appearance"}),k(os,{class:"social-links"}),c(a.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):m("",!0)]),_:3}))}}),us=b(cs,[["__scopeId","data-v-f2779853"]]),ds={key:0,class:"VPNav"},vs=p({__name:"VPNav",setup(e){const{isScreenOpen:t,closeScreen:n,toggleScreen:a}=ia(),{frontmatter:o}=P(),r=g(()=>o.value.navbar!==!1);return Se("close-screen",n),Y(()=>{ee&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(l,f)=>r.value?(s(),u("header",ds,[k(Ao,{"is-screen-open":i(t),onToggleScreen:i(a)},{"nav-bar-title-before":h(()=>[c(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":h(()=>[c(l.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":h(()=>[c(l.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":h(()=>[c(l.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),k(us,{open:i(t)},{"nav-screen-content-before":h(()=>[c(l.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":h(()=>[c(l.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):m("",!0)}}),fs=b(vs,[["__scopeId","data-v-ae24b3ad"]]),hs=["role","tabindex"],ms={key:1,class:"items"},ps=p({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(e){const t=e,{collapsed:n,collapsible:a,isLink:o,isActiveLink:r,hasActiveLink:l,hasChildren:f,toggle:d}=ct(g(()=>t.item)),y=g(()=>f.value?"section":"div"),L=g(()=>o.value?"a":"div"),$=g(()=>f.value?t.depth+2===7?"p":`h${t.depth+2}`:"p"),V=g(()=>o.value?void 0:"button"),M=g(()=>[[`level-${t.depth}`],{collapsible:a.value},{collapsed:n.value},{"is-link":o.value},{"is-active":r.value},{"has-active":l.value}]);function I(A){"key"in A&&A.key!=="Enter"||!t.item.link&&d()}function w(){t.item.link&&d()}return(A,B)=>{const O=W("VPSidebarItem",!0);return s(),_(C(y.value),{class:T(["VPSidebarItem",M.value])},{default:h(()=>[e.item.text?(s(),u("div",G({key:0,class:"item",role:V.value},Ge(e.item.items?{click:I,keydown:I}:{},!0),{tabindex:e.item.items&&0}),[B[1]||(B[1]=v("div",{class:"indicator"},null,-1)),e.item.link?(s(),_(E,{key:0,tag:L.value,class:"link",href:e.item.link,rel:e.item.rel,target:e.item.target},{default:h(()=>[(s(),_(C($.value),{class:"text",innerHTML:e.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(s(),_(C($.value),{key:1,class:"text",innerHTML:e.item.text},null,8,["innerHTML"])),e.item.collapsed!=null&&e.item.items&&e.item.items.length?(s(),u("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:w,onKeydown:Ue(w,["enter"]),tabindex:"0"},[...B[0]||(B[0]=[v("span",{class:"vpi-chevron-right caret-icon"},null,-1)])],32)):m("",!0)],16,hs)):m("",!0),e.item.items&&e.item.items.length?(s(),u("div",ms,[e.depth<5?(s(!0),u(x,{key:0},H(e.item.items,q=>(s(),_(O,{key:q.text,item:q,depth:e.depth+1},null,8,["item","depth"]))),128)):m("",!0)])):m("",!0)]),_:1},8,["class"])}}}),ks=b(ps,[["__scopeId","data-v-b3fd67f8"]]),_s=p({__name:"VPSidebarGroup",props:{items:{}},setup(e){const t=S(!0);let n=null;return U(()=>{n=setTimeout(()=>{n=null,t.value=!1},300)}),je(()=>{n!=null&&(clearTimeout(n),n=null)}),(a,o)=>(s(!0),u(x,null,H(e.items,r=>(s(),u("div",{key:r.text,class:T(["group",{"no-transition":t.value}])},[k(ks,{item:r,depth:0},null,8,["item"])],2))),128))}}),bs=b(_s,[["__scopeId","data-v-c40bc020"]]),gs={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},$s=p({__name:"VPSidebar",props:{open:{type:Boolean}},setup(e){const{sidebarGroups:t,hasSidebar:n}=D(),a=e,o=S(null),r=Ve(ee?document.body:null);F([a,o],()=>{var f;a.open?(r.value=!0,(f=o.value)==null||f.focus()):r.value=!1},{immediate:!0,flush:"post"});const l=S(0);return F(t,()=>{l.value+=1},{deep:!0}),(f,d)=>i(n)?(s(),u("aside",{key:0,class:T(["VPSidebar",{open:e.open}]),ref_key:"navEl",ref:o,onClick:d[0]||(d[0]=ze(()=>{},["stop"]))},[d[2]||(d[2]=v("div",{class:"curtain"},null,-1)),v("nav",gs,[d[1]||(d[1]=v("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),c(f.$slots,"sidebar-nav-before",{},void 0,!0),(s(),_(bs,{items:i(t),key:l.value},null,8,["items"])),c(f.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):m("",!0)}}),ys=b($s,[["__scopeId","data-v-319d5ca6"]]),Ps=p({__name:"VPSkipLink",setup(e){const{theme:t}=P(),n=X(),a=S();F(()=>n.path,()=>a.value.focus());function o({target:r}){const l=document.getElementById(decodeURIComponent(r.hash).slice(1));if(l){const f=()=>{l.removeAttribute("tabindex"),l.removeEventListener("blur",f)};l.setAttribute("tabindex","-1"),l.addEventListener("blur",f),l.focus(),window.scrollTo(0,0)}}return(r,l)=>(s(),u(x,null,[v("span",{ref_key:"backToTop",ref:a,tabindex:"-1"},null,512),v("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:o},N(i(t).skipToContentLabel||"Skip to content"),1)],64))}}),Ls=b(Ps,[["__scopeId","data-v-0b0ada53"]]),Vs=p({__name:"Layout",setup(e){const{isOpen:t,open:n,close:a}=D(),o=X();F(()=>o.path,a),lt(t,a);const{frontmatter:r}=P(),l=We(),f=g(()=>!!l["home-hero-image"]);return Se("hero-image-slot-exists",f),(d,y)=>{const L=W("Content");return i(r).layout!==!1?(s(),u("div",{key:0,class:T(["Layout",i(r).pageClass])},[c(d.$slots,"layout-top",{},void 0,!0),k(Ls),k(Je,{class:"backdrop",show:i(t),onClick:i(a)},null,8,["show","onClick"]),k(fs,null,{"nav-bar-title-before":h(()=>[c(d.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":h(()=>[c(d.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":h(()=>[c(d.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":h(()=>[c(d.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":h(()=>[c(d.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":h(()=>[c(d.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),k(sa,{open:i(t),onOpenMenu:i(n)},null,8,["open","onOpenMenu"]),k(ys,{open:i(t)},{"sidebar-nav-before":h(()=>[c(d.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":h(()=>[c(d.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),k(jn,null,{"page-top":h(()=>[c(d.$slots,"page-top",{},void 0,!0)]),"page-bottom":h(()=>[c(d.$slots,"page-bottom",{},void 0,!0)]),"not-found":h(()=>[c(d.$slots,"not-found",{},void 0,!0)]),"home-hero-before":h(()=>[c(d.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":h(()=>[c(d.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":h(()=>[c(d.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":h(()=>[c(d.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":h(()=>[c(d.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":h(()=>[c(d.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":h(()=>[c(d.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":h(()=>[c(d.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":h(()=>[c(d.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":h(()=>[c(d.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":h(()=>[c(d.$slots,"doc-before",{},void 0,!0)]),"doc-after":h(()=>[c(d.$slots,"doc-after",{},void 0,!0)]),"doc-top":h(()=>[c(d.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":h(()=>[c(d.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":h(()=>[c(d.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":h(()=>[c(d.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":h(()=>[c(d.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":h(()=>[c(d.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":h(()=>[c(d.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":h(()=>[c(d.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),k(Rn),c(d.$slots,"layout-bottom",{},void 0,!0)],2)):(s(),_(L,{key:1}))}}}),Ss=b(Vs,[["__scopeId","data-v-5d98c3a5"]]),Ns={Layout:Ss,enhanceApp:({app:e})=>{e.component("Badge",qe)}};export{Ns as t}; diff --git a/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.js b/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.js new file mode 100644 index 0000000..c35815f --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.js @@ -0,0 +1,18 @@ +import{_ as a,c as e,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const E=JSON.parse('{"title":"Architecture","description":"","frontmatter":{},"headers":[],"relativePath":"guide/architecture.md","filePath":"guide/architecture.md"}'),n={name:"guide/architecture.md"};function r(l,s,h,p,o,c){return i(),e("div",null,[...s[0]||(s[0]=[t(`

Architecture

EmptyGraph follows a strict Hexagonal Architecture (Ports & Adapters).

The Hexagon

mermaid
flowchart TD
+  User --> EG[EmptyGraph Facade]
+  EG --> GS[GraphService]
+  EG --> TS[TraversalService]
+  
+  GS --> Ports
+  TS --> Ports
+  
+  subgraph Ports
+    GPP[GraphPersistencePort]
+    ISP[IndexStoragePort]
+  end
+  
+  subgraph Adapters
+    Ports --> GGA[GitGraphAdapter]
+  end
+  
+  GGA --> Git[Git Plumbing]

Components

  • Domain Layer: Pure logic. GraphService manages nodes, TraversalService manages walking the graph.
  • Ports Layer: Interfaces that define how we talk to the outside world.
  • Adapters Layer: The implementation. GitGraphAdapter translates our domain calls into git CLI commands.

Why this matters

This decoupling means the "Brain" (Traversal) doesn't know it's running on Git. It just asks for "neighbors." This allowed us to swap in the Bitmap Index without changing the traversal algorithms.

`,8)])])}const k=a(n,[["render",r]]);export{E as __pageData,k as default}; diff --git a/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.lean.js b/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.lean.js new file mode 100644 index 0000000..7100ba0 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_architecture.md.CZgLXfX4.lean.js @@ -0,0 +1 @@ +import{_ as a,c as e,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const E=JSON.parse('{"title":"Architecture","description":"","frontmatter":{},"headers":[],"relativePath":"guide/architecture.md","filePath":"guide/architecture.md"}'),n={name:"guide/architecture.md"};function r(l,s,h,p,o,c){return i(),e("div",null,[...s[0]||(s[0]=[t("",8)])])}const k=a(n,[["render",r]]);export{E as __pageData,k as default}; diff --git a/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.js b/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.js new file mode 100644 index 0000000..10ee987 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as a,ae as n}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"Core Concepts","description":"","frontmatter":{},"headers":[],"relativePath":"guide/core-concepts.md","filePath":"guide/core-concepts.md"}'),s={name:"guide/core-concepts.md"};function r(i,e,h,d,c,l){return a(),o("div",null,[...e[0]||(e[0]=[n('

Core Concepts

To understand EmptyGraph, you need to understand three things: Nodes, Edges, and the Index.

1. The Node (A Ghost Commit)

A Node is just a Git Commit.

  • ID: The SHA-1 hash of the commit.
  • Data: The commit message (String/JSON).
  • Metadata: Author, Committer, Date.

Crucially, the commit points to the Empty Tree. This means it has no file content. It is a "Ghost" commit.

2. The Edge (Parent Pointers)

An Edge is the relationship between commits.

  • Git natively supports Backward Edges (Child points to Parent).
  • This creates a Directed Acyclic Graph (DAG).

3. The Index (The Cheat Code)

Git does not support Forward Edges (Parent points to Children). To find children, you have to scan the whole repo.

EmptyGraph solves this with a Roaring Bitmap Index.

  • We assign every SHA an integer ID.
  • We store adjacency lists in compressed bitmaps.
  • We save this index back into Git as a set of sharded JSON files.

When you ask graph.getChildren(parentSha), we check the index (O(1)). When you ask graph.getParents(childSha), we check the index (O(1)).

',14)])])}const g=t(s,[["render",r]]);export{m as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.lean.js b/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.lean.js new file mode 100644 index 0000000..ab8ca77 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_core-concepts.md.BOais_2r.lean.js @@ -0,0 +1 @@ +import{_ as t,c as o,o as a,ae as n}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"Core Concepts","description":"","frontmatter":{},"headers":[],"relativePath":"guide/core-concepts.md","filePath":"guide/core-concepts.md"}'),s={name:"guide/core-concepts.md"};function r(i,e,h,d,c,l){return a(),o("div",null,[...e[0]||(e[0]=[n("",14)])])}const g=t(s,[["render",r]]);export{m as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.js b/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.js new file mode 100644 index 0000000..4bd276a --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.js @@ -0,0 +1,34 @@ +import{_ as i,c as a,o as n,ae as t}from"./chunks/framework.DvGhUH3j.js";const o=JSON.parse('{"title":"Getting Started","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md"}'),h={name:"guide/getting-started.md"};function e(l,s,p,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t(`

Getting Started

Ready to perform some stunts?

Installation

bash
npm install @git-stunts/empty-graph @git-stunts/plumbing

The 30-Second Setup

You need two things:

  1. Plumbing: To talk to Git.
  2. Adapter: To translate Git to Graph.
javascript
import GitPlumbing from '@git-stunts/plumbing';
+import EmptyGraph, { GitGraphAdapter } from '@git-stunts/empty-graph';
+
+// 1. Point to a directory (it will be \`git init\`'d automatically if needed)
+const plumbing = new GitPlumbing({ cwd: './my-ghost-db' });
+
+// 2. Create the adapter
+const persistence = new GitGraphAdapter({ plumbing });
+
+// 3. Initialize the Graph
+const graph = new EmptyGraph({ persistence });
+
+// 4. Create your first Invisible Node
+const sha = await graph.createNode({
+  message: JSON.stringify({
+    type: 'Genesis',
+    payload: 'Hello from the other side'
+  })
+});
+
+console.log(\`Created node: \${sha}\`);

Reading it back

You can read by SHA, or iterate through history.

javascript
// Direct Read (O(1))
+const data = await graph.readNode(sha);
+
+// Stream History
+for await (const node of graph.iterateNodes({ ref: sha })) {
+  console.log(node.message);
+}

Enabling the "Supercharger" (Bitmap Index)

By default, we just use Git. But if you want to find children (traverse forward) instantly, you need the index.

javascript
// Build the index (scans history and saves a binary tree to git)
+const indexOid = await graph.rebuildIndex(sha);
+
+// Load it for O(1) powers
+await graph.loadIndex(indexOid);
+
+// Now you can look into the future
+const children = await graph.getChildren(sha);

Next Steps

`,16)])])}const E=i(h,[["render",e]]);export{o as __pageData,E as default}; diff --git a/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.lean.js b/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.lean.js new file mode 100644 index 0000000..9222fa9 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_getting-started.md.CjJfG1lj.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as n,ae as t}from"./chunks/framework.DvGhUH3j.js";const o=JSON.parse('{"title":"Getting Started","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started.md","filePath":"guide/getting-started.md"}'),h={name:"guide/getting-started.md"};function e(l,s,p,k,r,d){return n(),a("div",null,[...s[0]||(s[0]=[t("",16)])])}const E=i(h,[["render",e]]);export{o as __pageData,E as default}; diff --git a/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.js b/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.js new file mode 100644 index 0000000..06646b7 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as i,ae as s}from"./chunks/framework.DvGhUH3j.js";const p=JSON.parse('{"title":"What is this?","description":"","frontmatter":{},"headers":[],"relativePath":"guide/what-is-this.md","filePath":"guide/what-is-this.md"}'),a={name:"guide/what-is-this.md"};function r(n,t,h,d,l,u){return i(),o("div",null,[...t[0]||(t[0]=[s('

What is this?

EmptyGraph is a graph database that subverts Git's internal object model to store structured data invisibly.

It is a Git Stunt: a solution so unorthodox that if Linus Torvalds saw it, he would stop what he was doing, remove his glasses, rub his exhausted eyes, sigh deeply, and then, after a long silence, mutter: "You know what? Have fun," shake his head, and walk away.

The Core Subversion

Git is usually used to track files. EmptyGraph subverts this by using Git's Directed Acyclic Graph (DAG) to store structured data in the commits themselves.

Because all commits point to the "Empty Tree" (4b825dc642cb6eb9a060e54bf8d69288fbee4904), your data does not exist as files in the working directory—it exists entirely within the Git object database.

Why do this?

If you’re looking for the most "practical" way to build a database, you’d reach for Postgres. But the goal here isn't conventional efficiency; it’s first-principles engineering.

When we use Git to perform these "stunts," we accidentally inherit properties that take months to build into a standard SQL-based app:

  • Offline-First Synchronization: Git's distributed model handles replication for free.
  • Cryptographic Non-Repudiation: Every node's SHA proves its integrity and ancestry.
  • Universal Tooling: Use git log, git show, and git branch to inspect your database.
  • Infinite Point-in-Time Recovery: The reflog ensures you never truly lose a "deleted" node.

The Performance "Stunt"

Git is terrible at "future" lookups (finding children of a parent). To fix this, EmptyGraph builds a Secondary Roaring Bitmap Index.

This index provides O(1) lookups in both directions, making it 10,000x faster than raw Git traversal for complex graph queries, while still storing that index back into Git as a series of sharded blobs.

Is this production ready?

EmptyGraph is a stunt, not a product.

It's proof that Git's data model is more powerful than people realize. It's a legitimate tool for specific use cases (like AI agent memory or audit trails), but it's not a replacement for purpose-built graph databases like Neo4j if you need ACID transactions or multi-user row-level security.

Use it when Git's properties align with your needs. Don't use it just because it's clever.

',17)])])}const g=e(a,[["render",r]]);export{p as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.lean.js b/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.lean.js new file mode 100644 index 0000000..4211143 --- /dev/null +++ b/docs/.vitepress/dist/assets/guide_what-is-this.md.DGkKwESk.lean.js @@ -0,0 +1 @@ +import{_ as e,c as o,o as i,ae as s}from"./chunks/framework.DvGhUH3j.js";const p=JSON.parse('{"title":"What is this?","description":"","frontmatter":{},"headers":[],"relativePath":"guide/what-is-this.md","filePath":"guide/what-is-this.md"}'),a={name:"guide/what-is-this.md"};function r(n,t,h,d,l,u){return i(),o("div",null,[...t[0]||(t[0]=[s("",17)])])}const g=e(a,[["render",r]]);export{p as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.js b/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.js new file mode 100644 index 0000000..0ca8b7c --- /dev/null +++ b/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.js @@ -0,0 +1,235 @@ +import{_ as a,c as n,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const o=JSON.parse('{"title":"Roaring Bitmap Index Architecture","description":"","frontmatter":{},"headers":[],"relativePath":"images/bitmap-index.md","filePath":"images/bitmap-index.md"}'),e={name:"images/bitmap-index.md"};function l(p,s,h,E,r,k){return i(),n("div",null,[...s[0]||(s[0]=[t(`

Roaring Bitmap Index Architecture

This diagram illustrates how EMPTY GRAPH uses Roaring Bitmaps to provide O(1) lookups for graph traversal operations.

Overview Diagram

mermaid
flowchart TB
+    subgraph GRAPH["Git Commit Graph"]
+        direction TB
+        A["Node A<br/>(root commit)"]
+        B["Node B<br/>(branch 1)"]
+        C["Node C<br/>(branch 2)"]
+        D["Node D<br/>(merge commit)"]
+
+        A --> B
+        A --> C
+        B --> D
+        C --> D
+    end
+
+    subgraph INDEX["Bitmap Index Structure"]
+        direction TB
+
+        subgraph SHA_TO_ID["SHA to ID Mapping"]
+            M1["meta_a1.json<br/>{ 'a1b2c3...': 0 }"]
+            M2["meta_b2.json<br/>{ 'b2c3d4...': 1 }"]
+            M3["meta_c3.json<br/>{ 'c3d4e5...': 2 }"]
+            M4["meta_d4.json<br/>{ 'd4e5f6...': 3 }"]
+        end
+
+        subgraph FWD["Forward Index (fwd)<br/>parent -> children IDs"]
+            F1["shards_fwd_a1.json<br/>A: bitmap{1, 2}"]
+            F2["shards_fwd_b2.json<br/>B: bitmap{3}"]
+            F3["shards_fwd_c3.json<br/>C: bitmap{3}"]
+        end
+
+        subgraph REV["Reverse Index (rev)<br/>child -> parent IDs"]
+            R2["shards_rev_b2.json<br/>B: bitmap{0}"]
+            R3["shards_rev_c3.json<br/>C: bitmap{0}"]
+            R4["shards_rev_d4.json<br/>D: bitmap{1, 2}"]
+        end
+    end
+
+    GRAPH -.->|"Build Index"| INDEX

SHA to Numeric ID Mapping

SHAs are mapped to compact numeric IDs for efficient bitmap storage:

mermaid
flowchart LR
+    subgraph SHAs["40-char Git SHAs"]
+        SHA_A["a1b2c3d4e5..."]
+        SHA_B["b2c3d4e5f6..."]
+        SHA_C["c3d4e5f6a7..."]
+        SHA_D["d4e5f6a7b8..."]
+    end
+
+    subgraph IDs["Numeric IDs"]
+        ID0["0"]
+        ID1["1"]
+        ID2["2"]
+        ID3["3"]
+    end
+
+    SHA_A --> ID0
+    SHA_B --> ID1
+    SHA_C --> ID2
+    SHA_D --> ID3
+
+    style ID0 fill:#e1f5fe
+    style ID1 fill:#e1f5fe
+    style ID2 fill:#e1f5fe
+    style ID3 fill:#e1f5fe

Query Flow: getChildren(A)

mermaid
sequenceDiagram
+    participant User
+    participant Reader as BitmapIndexReader
+    participant Meta as meta_a1.json
+    participant Fwd as shards_fwd_a1.json
+    participant Bitmap as RoaringBitmap32
+
+    User->>Reader: getChildren("a1b2c3...")
+
+    Note over Reader: 1. Extract SHA prefix "a1"
+
+    Reader->>Fwd: Load shard (lazy, cached)
+    Fwd-->>Reader: { "a1b2c3...": "base64bitmap" }
+
+    Note over Reader: 2. Decode bitmap for SHA
+
+    Reader->>Bitmap: deserialize(base64)
+    Bitmap-->>Reader: bitmap{1, 2}
+
+    Note over Reader: 3. Convert IDs to SHAs
+
+    Reader->>Meta: Load all meta shards (cached)
+    Meta-->>Reader: ID 1 = "b2c3d4...", ID 2 = "c3d4e5..."
+
+    Reader-->>User: ["b2c3d4...", "c3d4e5..."]
+
+    Note over User,Reader: O(1) lookup via bitmap!

Warning: First query loads all meta shards O(n); subsequent queries O(1)

BitmapIndexReader.getChildren depends on _buildIdToShaMapping which loads all meta shards (up to 256) on the first query. Only subsequent lookups are O(1). Note that the LRU cache (default 100) can be exceeded during initial load.

Query Flow: getParents(D)

mermaid
sequenceDiagram
+    participant User
+    participant Reader as BitmapIndexReader
+    participant Rev as shards_rev_d4.json
+    participant Bitmap as RoaringBitmap32
+    participant Meta as meta_*.json
+
+    User->>Reader: getParents("d4e5f6...")
+
+    Note over Reader: 1. Extract SHA prefix "d4"
+
+    Reader->>Rev: Load reverse shard (lazy, cached)
+    Rev-->>Reader: { "d4e5f6...": "base64bitmap" }
+
+    Note over Reader: 2. Decode bitmap for SHA
+
+    Reader->>Bitmap: deserialize(base64)
+    Bitmap-->>Reader: bitmap{1, 2}
+
+    Note over Reader: 3. Convert IDs to SHAs
+
+    Reader->>Meta: Lookup IDs 1 and 2
+    Meta-->>Reader: ID 1 = "b2c3d4...", ID 2 = "c3d4e5..."
+
+    Reader-->>User: ["b2c3d4...", "c3d4e5..."]
+
+    Note over User,Reader: Merge commits with multiple<br/>parents resolved in O(1)!

Sharding Strategy

Shards are organized by 2-character SHA prefix for efficient lazy loading:

mermaid
flowchart TB
+    subgraph Storage["Index Storage (256 possible prefixes)"]
+        direction LR
+
+        subgraph Prefix_00["Prefix '00'"]
+            meta_00["meta_00.json"]
+            fwd_00["shards_fwd_00.json"]
+            rev_00["shards_rev_00.json"]
+        end
+
+        subgraph Prefix_a1["Prefix 'a1'"]
+            meta_a1["meta_a1.json"]
+            fwd_a1["shards_fwd_a1.json"]
+            rev_a1["shards_rev_a1.json"]
+        end
+
+        subgraph Prefix_ff["Prefix 'ff'"]
+            meta_ff["meta_ff.json"]
+            fwd_ff["shards_fwd_ff.json"]
+            rev_ff["shards_rev_ff.json"]
+        end
+
+        dots["..."]
+    end
+
+    subgraph Query["Query: getChildren('a1b2c3...')"]
+        Q1["1. Extract prefix 'a1'"]
+        Q2["2. Load only shards_fwd_a1.json"]
+        Q3["3. Other shards stay unloaded"]
+    end
+
+    Query --> Prefix_a1
+
+    style Prefix_a1 fill:#c8e6c9
+    style Prefix_00 fill:#f5f5f5
+    style Prefix_ff fill:#f5f5f5

Why Roaring Bitmaps Are Fast

mermaid
flowchart TB
+    subgraph Traditional["Traditional Approach"]
+        direction TB
+        T1["Store edges as arrays"]
+        T2["children: ['sha1', 'sha2', ...]"]
+        T3["O(n) to check membership"]
+        T4["Large storage for many edges"]
+
+        T1 --> T2 --> T3 --> T4
+    end
+
+    subgraph Roaring["Roaring Bitmap Approach"]
+        direction TB
+        R1["Store IDs in compressed bitmap"]
+        R2["children: bitmap{1, 2, 3, ...}"]
+        R3["O(1) to check membership"]
+        R4["Highly compressed storage"]
+
+        R1 --> R2 --> R3 --> R4
+    end
+
+    subgraph Benefits["Key Benefits"]
+        B1["Compression: Run-length encoding for dense ranges"]
+        B2["Fast Operations: AND, OR, XOR on bitmaps"]
+        B3["Memory Efficient: 10-100x smaller than arrays"]
+        B4["Lazy Loading: Only load shards you need"]
+    end
+
+    Traditional -.->|"vs"| Roaring
+    Roaring --> Benefits
+
+    style Roaring fill:#e8f5e9
+    style Traditional fill:#ffebee
+    style Benefits fill:#e3f2fd

Complete Index Structure Example

mermaid
flowchart TB
+    subgraph Graph["Example Git Graph"]
+        A["A (id=0)<br/>sha: a1b2c3..."]
+        B["B (id=1)<br/>sha: b2c3d4..."]
+        C["C (id=2)<br/>sha: c3d4e5..."]
+        D["D (id=3)<br/>sha: d4e5f6..."]
+
+        A -->|"parent"| B
+        A -->|"parent"| C
+        B -->|"parent"| D
+        C -->|"parent"| D
+    end
+
+    subgraph Forward["Forward Index (fwd)<br/>Who are my children?"]
+        FWD_A["A -> bitmap{1, 2}<br/>(children: B, C)"]
+        FWD_B["B -> bitmap{3}<br/>(child: D)"]
+        FWD_C["C -> bitmap{3}<br/>(child: D)"]
+        FWD_D["D -> bitmap{}<br/>(no children)"]
+    end
+
+    subgraph Reverse["Reverse Index (rev)<br/>Who are my parents?"]
+        REV_A["A -> bitmap{}<br/>(no parents - root)"]
+        REV_B["B -> bitmap{0}<br/>(parent: A)"]
+        REV_C["C -> bitmap{0}<br/>(parent: A)"]
+        REV_D["D -> bitmap{1, 2}<br/>(parents: B, C)"]
+    end
+
+    Graph --> Forward
+    Graph --> Reverse
+
+    style FWD_A fill:#bbdefb
+    style FWD_B fill:#bbdefb
+    style FWD_C fill:#bbdefb
+    style FWD_D fill:#bbdefb
+    style REV_A fill:#c8e6c9
+    style REV_B fill:#c8e6c9
+    style REV_C fill:#c8e6c9
+    style REV_D fill:#c8e6c9

Shard File Format

Each shard file contains a versioned envelope with checksum for integrity:

mermaid
flowchart TB
+    subgraph Envelope["Shard Envelope"]
+        direction TB
+        V["version: 1"]
+        C["checksum: 'sha256...'"]
+        D["data: {...}"]
+    end
+
+    subgraph MetaShard["meta_a1.json"]
+        MD["data: {<br/>  'a1b2c3...': 0,<br/>  'a1f2e3...': 42,<br/>  ...<br/>}"]
+    end
+
+    subgraph BitmapShard["shards_fwd_a1.json"]
+        BD["data: {<br/>  'a1b2c3...': 'base64bitmap',<br/>  'a1f2e3...': 'base64bitmap',<br/>  ...<br/>}"]
+    end
+
+    Envelope --> MetaShard
+    Envelope --> BitmapShard

Summary

ComponentPurposeLookup Time
meta_XX.jsonSHA to numeric ID mappingO(1)
shards_fwd_XX.jsonForward edges (parent to children)O(1)
shards_rev_XX.jsonReverse edges (child to parents)O(1)
LRU CacheAvoid re-loading recently used shardsO(1)

The combination of:

  1. Numeric IDs (compact representation)
  2. Roaring Bitmaps (compressed, fast set operations)
  3. Sharding by prefix (lazy loading, reduced memory)
  4. LRU caching (avoid repeated I/O)

...enables EMPTY GRAPH to traverse massive Git commit graphs with constant-time lookups.

`,27)])])}const c=a(e,[["render",l]]);export{o as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.lean.js b/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.lean.js new file mode 100644 index 0000000..20fa517 --- /dev/null +++ b/docs/.vitepress/dist/assets/images_bitmap-index.md.CS_4KAjN.lean.js @@ -0,0 +1 @@ +import{_ as a,c as n,o as i,ae as t}from"./chunks/framework.DvGhUH3j.js";const o=JSON.parse('{"title":"Roaring Bitmap Index Architecture","description":"","frontmatter":{},"headers":[],"relativePath":"images/bitmap-index.md","filePath":"images/bitmap-index.md"}'),e={name:"images/bitmap-index.md"};function l(p,s,h,E,r,k){return i(),n("div",null,[...s[0]||(s[0]=[t("",27)])])}const c=a(e,[["render",l]]);export{o as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/index.md.BV983U1U.js b/docs/.vitepress/dist/assets/index.md.BV983U1U.js new file mode 100644 index 0000000..b66f0f6 --- /dev/null +++ b/docs/.vitepress/dist/assets/index.md.BV983U1U.js @@ -0,0 +1,17 @@ +import{_ as i,c as a,o as t,ae as n}from"./chunks/framework.DvGhUH3j.js";const F=JSON.parse(`{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"EmptyGraph","text":"A graph database that lives inside Git.","tagline":"Invisible storage. O(1) lookups. Zero files.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/what-is-this"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/git-stunts/empty-graph"}]},"features":[{"title":"👻 Invisible Storage","details":"Stores data in the Git object database using the empty-tree pattern. No files in your working directory."},{"title":"⚡ O(1) Lookups","details":"Secondary Roaring Bitmap index provides blazing fast parent/child lookups, bypassing Git's native limitations."},{"title":"🌊 Streaming First","details":"Handle millions of nodes with constant memory overhead. Designed for high-performance systems and AI memory."},{"title":"🗺️ Advanced Traversal","details":"Built-in BFS, DFS, Dijkstra, and A* search for complex relationship analysis."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),e={name:"index.md"};function l(h,s,p,k,r,d){return t(),a("div",null,[...s[0]||(s[0]=[n(`

The "Wait, what?" Moment

bash
# Directory is empty
+$ ls -la
+total 0
+drwxr-xr-x  2 james  staff  64 Jan 29 12:00 .
+
+# Create a graph node (behind the scenes)
+$ node create-node.js "{"hello": "world"}"
+Created node: abc123def456...
+
+# Still no files!
+$ ls -la
+total 0
+drwxr-xr-x  2 james  staff  64 Jan 29 12:00 .
+
+# But Git knows...
+$ git log --format=%B -n 1 abc123def
+{"hello": "world"}

Why it exists

Graph databases are usually a $3B market requiring dedicated infra. EmptyGraph asks: "What if the graph database was just Git?"

It's a stunt, yes. But it's also a legitimate tool for offline-first data, audit trails, and AI agent memory that needs to be distributed, versioned, and immutable.

`,6)])])}const g=i(e,[["render",l]]);export{F as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/index.md.BV983U1U.lean.js b/docs/.vitepress/dist/assets/index.md.BV983U1U.lean.js new file mode 100644 index 0000000..473b810 --- /dev/null +++ b/docs/.vitepress/dist/assets/index.md.BV983U1U.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ae as n}from"./chunks/framework.DvGhUH3j.js";const F=JSON.parse(`{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"EmptyGraph","text":"A graph database that lives inside Git.","tagline":"Invisible storage. O(1) lookups. Zero files.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/what-is-this"},{"theme":"alt","text":"View on GitHub","link":"https://github.com/git-stunts/empty-graph"}]},"features":[{"title":"👻 Invisible Storage","details":"Stores data in the Git object database using the empty-tree pattern. No files in your working directory."},{"title":"⚡ O(1) Lookups","details":"Secondary Roaring Bitmap index provides blazing fast parent/child lookups, bypassing Git's native limitations."},{"title":"🌊 Streaming First","details":"Handle millions of nodes with constant memory overhead. Designed for high-performance systems and AI memory."},{"title":"🗺️ Advanced Traversal","details":"Built-in BFS, DFS, Dijkstra, and A* search for complex relationship analysis."}]},"headers":[],"relativePath":"index.md","filePath":"index.md"}`),e={name:"index.md"};function l(h,s,p,k,r,d){return t(),a("div",null,[...s[0]||(s[0]=[n("",6)])])}const g=i(e,[["render",l]]);export{F as __pageData,g as default}; diff --git a/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 b/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 new file mode 100644 index 0000000..b6b603d Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 b/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 new file mode 100644 index 0000000..def40a4 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 b/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 new file mode 100644 index 0000000..e070c3d Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 b/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 new file mode 100644 index 0000000..a3c16ca Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 b/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 new file mode 100644 index 0000000..2210a89 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 b/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 new file mode 100644 index 0000000..790d62d Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 b/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 new file mode 100644 index 0000000..1eec077 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 b/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 new file mode 100644 index 0000000..2cfe615 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 b/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 new file mode 100644 index 0000000..e3886dd Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 b/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 new file mode 100644 index 0000000..36d6748 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 b/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 new file mode 100644 index 0000000..2bed1e8 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 b/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 new file mode 100644 index 0000000..9a8d1e2 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 b/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 new file mode 100644 index 0000000..07d3c53 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 differ diff --git a/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 b/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 new file mode 100644 index 0000000..57bdc22 Binary files /dev/null and b/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 differ diff --git a/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.js b/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.js new file mode 100644 index 0000000..8874ca2 --- /dev/null +++ b/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.js @@ -0,0 +1 @@ +import{_ as a,c as t,o,ae as r}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"The Bitmap Index (Internals)","description":"","frontmatter":{},"headers":[],"relativePath":"internals/bitmap-index.md","filePath":"internals/bitmap-index.md"}'),n={name:"internals/bitmap-index.md"};function i(s,e,d,l,h,c){return o(),t("div",null,[...e[0]||(e[0]=[r('

The Bitmap Index (Internals)

Warning: This is deep magic. You don't need to know this to use the library, but it helps if you want to understand the performance characteristics.

The Problem

Git stores Child -> Parent links efficiently. It stores Parent -> Child links... not at all.

The Solution

We map every 40-character SHA-1 to a 32-bit Integer ID. We then use Roaring Bitmaps to store the adjacency matrix.

Sharding

To avoid loading a 100MB index for a single query, we shard the index by SHA prefix (2 chars -> 256 shards).

  • meta_ab.json: ID mappings for SHAs starting with ab.
  • shards_fwd_ab.json: Forward edges for ab.
  • shards_rev_ab.json: Backward edges for ab.

This allows us to perform "Lazy Loading". We only load the shards relevant to the nodes you are currently visiting.

',10)])])}const u=a(n,[["render",i]]);export{m as __pageData,u as default}; diff --git a/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.lean.js b/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.lean.js new file mode 100644 index 0000000..4568db1 --- /dev/null +++ b/docs/.vitepress/dist/assets/internals_bitmap-index.md.C00etvr2.lean.js @@ -0,0 +1 @@ +import{_ as a,c as t,o,ae as r}from"./chunks/framework.DvGhUH3j.js";const m=JSON.parse('{"title":"The Bitmap Index (Internals)","description":"","frontmatter":{},"headers":[],"relativePath":"internals/bitmap-index.md","filePath":"internals/bitmap-index.md"}'),n={name:"internals/bitmap-index.md"};function i(s,e,d,l,h,c){return o(),t("div",null,[...e[0]||(e[0]=[r("",10)])])}const u=a(n,[["render",i]]);export{m as __pageData,u as default}; diff --git a/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.js b/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.js new file mode 100644 index 0000000..0796b21 --- /dev/null +++ b/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as n}from"./chunks/framework.DvGhUH3j.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"internals/plumbing.md","filePath":"internals/plumbing.md"}'),a={name:"internals/plumbing.md"};function r(s,i,o,c,p,l){return n(),t("div")}const d=e(a,[["render",r]]);export{_ as __pageData,d as default}; diff --git a/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.lean.js b/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.lean.js new file mode 100644 index 0000000..0796b21 --- /dev/null +++ b/docs/.vitepress/dist/assets/internals_plumbing.md.CODhq3GG.lean.js @@ -0,0 +1 @@ +import{_ as e,c as t,o as n}from"./chunks/framework.DvGhUH3j.js";const _=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"internals/plumbing.md","filePath":"internals/plumbing.md"}'),a={name:"internals/plumbing.md"};function r(s,i,o,c,p,l){return n(),t("div")}const d=e(a,[["render",r]]);export{_ as __pageData,d as default}; diff --git a/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.js b/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.js new file mode 100644 index 0000000..e5a84a9 --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.js @@ -0,0 +1,18 @@ +import{_ as i,c as a,o as t,ae as n}from"./chunks/framework.DvGhUH3j.js";const d=JSON.parse('{"title":"Event Sourcing","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/event-sourcing.md","filePath":"stunts/event-sourcing.md"}'),e={name:"stunts/event-sourcing.md"};function h(l,s,p,k,r,o){return t(),a("div",null,[...s[0]||(s[0]=[n(`

Event Sourcing

The Stunt: Treating Git commits as immutable domain events, and "replaying" history to build application state.

Event Sourcing is a pattern where you don't store the "current state" (e.g., User: { name: "Alice" }). Instead, you store the sequence of events that led there:

  1. UserCreated { name: "Alice" }
  2. UserRenamed { newName: "Al" }

Git is natively an event store. It is an append-only log of immutable changes.

The Implementation

With EmptyGraph, every node is an event.

javascript
// 1. Store an event
+await graph.createNode({
+  message: JSON.stringify({ type: 'OrderPlaced', amount: 100 }),
+  parents: [previousEventSha] // Link to the chain
+});
+
+// 2. Replay to build state
+let balance = 0;
+// Note: ancestors() goes backwards in time, so we reverse it
+const history = [];
+for await (const node of graph.traversal.ancestors({ sha: 'HEAD' })) {
+  history.push(JSON.parse(node.message));
+}
+
+for (const event of history.reverse()) {
+  if (event.type === 'OrderPlaced') balance += event.amount;
+  if (event.type === 'Refunded') balance -= event.amount;
+}

Branching = Alternate Timelines

Because it's Git, you can branch your event stream.

  • Main Branch: The "official" history.
  • Feature Branch: A "What If" simulation.

You can replay a "simulation branch" to see what the state would be if you cancelled an order, without affecting the main timeline. This is incredibly powerful for financial modeling or game state prediction.

Cryptographic Proof

Every state is cryptographically verifiable. If you have the SHA of the tip of the branch, you have a mathematical guarantee that the entire history leading up to it has not been tampered with. This is built-in Blockchain tech, without the Blockchain hype.

`,14)])])}const c=i(e,[["render",h]]);export{d as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.lean.js b/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.lean.js new file mode 100644 index 0000000..dbc7cd1 --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_event-sourcing.md.hd1e6A6k.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ae as n}from"./chunks/framework.DvGhUH3j.js";const d=JSON.parse('{"title":"Event Sourcing","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/event-sourcing.md","filePath":"stunts/event-sourcing.md"}'),e={name:"stunts/event-sourcing.md"};function h(l,s,p,k,r,o){return t(),a("div",null,[...s[0]||(s[0]=[n("",14)])])}const c=i(e,[["render",h]]);export{d as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.js b/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.js new file mode 100644 index 0000000..98d881d --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.js @@ -0,0 +1,9 @@ +import{_ as i,c as a,o as t,ae as e}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Invisible Metadata","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/invisible-storage.md","filePath":"stunts/invisible-storage.md"}'),n={name:"stunts/invisible-storage.md"};function h(o,s,l,r,p,k){return t(),a("div",null,[...s[0]||(s[0]=[e(`

Invisible Metadata

The Stunt: Storing rich application state inside your .git folder without creating a single file in your working directory.

This is the feature that usually breaks people's brains.

When you use EmptyGraph, you are interacting with Git, but you are not touching the "Index" (staging area) or the "Work Tree" (your files). You are bypassing them and writing directly to the Object Database (the .git/objects folder).

The "Empty Tree" Pattern

Every commit in Git points to a "Tree" object (a snapshot of a directory). Usually, that tree contains your source code.

But a tree can be empty. The SHA-1 of an empty tree is always constant:

4b825dc642cb6eb9a060e54bf8d69288fbee4904

We create commits that point to this tree.

  • Files: 0
  • Data: Stored in the "Commit Message"
  • History: Fully preserved

Use Case: The "Shadow" Database

Imagine you are building a CLI tool. You want to store configuration, usage history, or user preferences.

The Old Way:

  • Write to ~/.config/my-tool/config.json.
  • Now you have to manage file permissions, paths, JSON parsing corruption.

The EmptyGraph Way:

  • Initialize a hidden git repo.
  • Write updates as commits to a detached branch or a custom ref (e.g., refs/shadow/config).
javascript
// Write config
+const sha = await graph.createNode({
+  message: JSON.stringify({ theme: 'dark', retries: 3 })
+});
+await plumbing.updateRef('refs/shadow/config', sha);
+
+// Read config
+const headSha = await plumbing.readRef('refs/shadow/config');
+const config = JSON.parse(await graph.readNode(headSha));

Why?

  1. It's Clean: No pollution of the user's home directory with random config files.
  2. It's Auditable: You have a complete history of every configuration change ever made. "Why did my theme change?" -> Check the log.
  3. It's Syncable: It's just a Git ref. You can git push it to a remote for backup or sync it between machines.

The "Rootkit" Database

We call this the "Rootkit" pattern (metaphorically!) because it exists in a layer underneath what the user perceives as "the filesystem." It is persistent, versioned, and invisible.

`,21)])])}const c=i(n,[["render",h]]);export{g as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.lean.js b/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.lean.js new file mode 100644 index 0000000..265a94f --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_invisible-storage.md.CtCpDpSQ.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ae as e}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Invisible Metadata","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/invisible-storage.md","filePath":"stunts/invisible-storage.md"}'),n={name:"stunts/invisible-storage.md"};function h(o,s,l,r,p,k){return t(),a("div",null,[...s[0]||(s[0]=[e("",21)])])}const c=i(n,[["render",h]]);export{g as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.js b/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.js new file mode 100644 index 0000000..9fe307c --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.js @@ -0,0 +1,19 @@ +import{_ as i,c as a,o as t,ae as e}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Resource-Aware Routing","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/lagrangian-routing.md","filePath":"stunts/lagrangian-routing.md"}'),n={name:"stunts/lagrangian-routing.md"};function h(l,s,r,p,o,k){return t(),a("div",null,[...s[0]||(s[0]=[e(`

Resource-Aware Routing

The Stunt: Routing through a graph based on "cost" (CPU, Memory, Latency) rather than just distance, using Dijkstra and A* on top of a Git repo.

Most graph traversals just look for the shortest path (fewest hops). But in distributed systems, the shortest path might be the most expensive.

EmptyGraph implements "Lagrangian Pathfinding"—a fancy term for "we check the price tag before we walk through the door."

The Scenario

Imagine you are building an AI Agent that needs to execute a sequence of tasks.

  • Node A: "Download Data" (High Bandwidth)
  • Node B: "Process Data" (High CPU)
  • Node C: "Save to S3" (Low Cost)

If Node B is overloaded, you don't want to route through it, even if it's the "shortest" path. You want the "cheapest" path.

The Code

We use weightedShortestPath with a custom weightProvider. This function is async, meaning it can fetch real-time metrics (from Prometheus, a JSON file, or another Git commit) to decide the cost of an edge.

javascript
const { path, totalCost } = await graph.traversal.weightedShortestPath({
+  from: startSha,
+  to: targetSha,
+  
+  // This is where the magic happens
+  weightProvider: async (fromSha, toSha) => {
+    // 1. Read the node data
+    const message = await graph.readNode(toSha);
+    const event = JSON.parse(message);
+    
+    // 2. Extract metrics (simulated or real)
+    const cpuLoad = event.metrics?.cpu ?? 1; // 1.0 = 100% load
+    const memory = event.metrics?.mem ?? 1;  // 1.0 = 1GB
+    
+    // 3. Calculate Lagrangian cost
+    // Cost = CPU + 1.5 * Memory
+    return cpuLoad + (memory * 1.5);
+  }
+});

Why this is cool

  1. Dynamic Topography: The shape of your graph changes based on the state of the nodes, not just their connections.
  2. Invisible Backend: You can store the metric history in the graph itself as a separate branch, and query it during traversal.
  3. A Optimization:* If you know the heuristic distance (e.g., "how many steps left?"), you can use aStarSearch to prioritize exploring promising paths first, massively pruning the search space.

Performance Note

This isn't just a toy. Because we use a MinHeap and a Roaring Bitmap Index, this traversal is extremely efficient. We only load the node data when we actually consider the edge, and we cache heavily.

`,15)])])}const c=i(n,[["render",h]]);export{g as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.lean.js b/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.lean.js new file mode 100644 index 0000000..29b99ab --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_lagrangian-routing.md.DmVl5Oa4.lean.js @@ -0,0 +1 @@ +import{_ as i,c as a,o as t,ae as e}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Resource-Aware Routing","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/lagrangian-routing.md","filePath":"stunts/lagrangian-routing.md"}'),n={name:"stunts/lagrangian-routing.md"};function h(l,s,r,p,o,k){return t(),a("div",null,[...s[0]||(s[0]=[e("",15)])])}const c=i(n,[["render",h]]);export{g as __pageData,c as default}; diff --git a/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.js b/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.js new file mode 100644 index 0000000..33c3b97 --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.js @@ -0,0 +1,4 @@ +import{_ as e,c as a,o as s,ae as i}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Infinite Memory Streaming","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/streaming.md","filePath":"stunts/streaming.md"}'),n={name:"stunts/streaming.md"};function r(o,t,h,l,d,p){return s(),a("div",null,[...t[0]||(t[0]=[i(`

Infinite Memory Streaming

The Stunt: Processing a graph with 10 million nodes on a Raspberry Pi without crashing Node.js.

Git history is linear, but it can be massive. If you try to git log the Linux kernel and load it all into a Javascript array, you will crash with an OutOfMemory error immediately.

EmptyGraph is designed to never hold the full graph in memory.

The Generator Pattern

We use async generators (async function*) for everything.

javascript
// This will never OOM, even if 'HEAD' has 1 billion commits.
+for await (const node of graph.iterateNodes({ ref: 'HEAD' })) {
+  process(node);
+}

How it works (Internals)

Under the hood, we spawn a git log process and pipe its stdout through a custom binary parser.

  1. Spawn: git log --format=...
  2. Stream: We receive chunks of Buffer data.
  3. Parse: We scan for NUL byte delimiters (which we use because they are illegal in git messages, making them 100% safe).
  4. Yield: As soon as we have a full record, we yield it and discard the buffer.

This means your memory usage is determined by the size of a single node, not the size of the graph.

Benchmark

We ran this on a graph with 100,000 nodes containing JSON payloads.

| Metric | Result |

StringResult
Heap Used~40 MB (Constant)
Throughput~24,000 nodes / sec
Crash?Never.

Why this matters

If you are building an audit system or an event store, you can't assume your data fits in RAM. This architecture guarantees that your system remains stable as your data grows from "Prototype" size to "Production" size.

`,17)])])}const k=e(n,[["render",r]]);export{g as __pageData,k as default}; diff --git a/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.lean.js b/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.lean.js new file mode 100644 index 0000000..537e412 --- /dev/null +++ b/docs/.vitepress/dist/assets/stunts_streaming.md.BzupMMFw.lean.js @@ -0,0 +1 @@ +import{_ as e,c as a,o as s,ae as i}from"./chunks/framework.DvGhUH3j.js";const g=JSON.parse('{"title":"Infinite Memory Streaming","description":"","frontmatter":{},"headers":[],"relativePath":"stunts/streaming.md","filePath":"stunts/streaming.md"}'),n={name:"stunts/streaming.md"};function r(o,t,h,l,d,p){return s(),a("div",null,[...t[0]||(t[0]=[i("",17)])])}const k=e(n,[["render",r]]);export{g as __pageData,k as default}; diff --git a/docs/.vitepress/dist/assets/style.B8-ykPZs.css b/docs/.vitepress/dist/assets/style.B8-ykPZs.css new file mode 100644 index 0000000..89748fc --- /dev/null +++ b/docs/.vitepress/dist/assets/style.B8-ykPZs.css @@ -0,0 +1 @@ +@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: #3c3c43;--vp-c-text-2: #67676c;--vp-c-text-3: #929295}.dark{--vp-c-text-1: #dfdfd6;--vp-c-text-2: #98989f;--vp-c-text-3: #6a6a71}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:lang(es),:lang(pt){--vp-code-copy-copied-text-content: "Copiado"}:lang(fa){--vp-code-copy-copied-text-content: "کپی شد"}:lang(ko){--vp-code-copy-copied-text-content: "복사됨"}:lang(ru){--vp-code-copy-copied-text-content: "Скопировано"}:lang(zh){--vp-code-copy-copied-text-content: "已复制"}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{color:inherit;text-decoration:inherit}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:var(--vp-c-text-3)}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}textarea{resize:vertical}select{-webkit-appearance:none}fieldset{margin:0;padding:0}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.4;transition:filter .35s,opacity .35s}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;-webkit-user-select:none;user-select:none;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(:is(.no-icon,svg a,:has(img,svg))):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-c79a1216]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-c79a1216],.VPBackdrop.fade-leave-to[data-v-c79a1216]{opacity:0}.VPBackdrop.fade-leave-active[data-v-c79a1216]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-c79a1216]{display:none}}.NotFound[data-v-d6be1790]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-d6be1790]{padding:96px 32px 168px}}.code[data-v-d6be1790]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-d6be1790]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-d6be1790]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-d6be1790]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-d6be1790]{padding-top:20px}.link[data-v-d6be1790]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-d6be1790]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-b933a997]{position:relative;z-index:1}.nested[data-v-b933a997]{padding-right:16px;padding-left:16px}.outline-link[data-v-b933a997]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-b933a997]:hover,.outline-link.active[data-v-b933a997]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-b933a997]{padding-left:13px}.VPDocAsideOutline[data-v-a5bbad30]{display:none}.VPDocAsideOutline.has-outline[data-v-a5bbad30]{display:block}.content[data-v-a5bbad30]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-a5bbad30]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-a5bbad30]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-3f215769]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-3f215769]{flex-grow:1}.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-3f215769] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-3f215769] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-e98dd255]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-e98dd255]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-e257564d]{margin-top:64px}.edit-info[data-v-e257564d]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-e257564d]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-e257564d]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-e257564d]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-e257564d]{margin-right:8px}.prev-next[data-v-e257564d]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-e257564d]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-e257564d]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-e257564d]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-e257564d]{margin-left:auto;text-align:right}.desc[data-v-e257564d]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-e257564d]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-39a288b8]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-39a288b8]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-39a288b8]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-39a288b8]{display:flex;justify-content:center}.VPDoc .aside[data-v-39a288b8]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-39a288b8]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-39a288b8]{max-width:1104px}}.container[data-v-39a288b8]{margin:0 auto;width:100%}.aside[data-v-39a288b8]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-39a288b8]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-39a288b8]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-39a288b8]::-webkit-scrollbar{display:none}.aside-curtain[data-v-39a288b8]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-39a288b8]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-39a288b8]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-39a288b8]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-39a288b8]{order:1;margin:0;min-width:640px}}.content-container[data-v-39a288b8]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-39a288b8]{max-width:688px}.VPButton[data-v-fa7799d5]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-fa7799d5]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-fa7799d5]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-fa7799d5]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-fa7799d5]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-fa7799d5]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-fa7799d5]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-fa7799d5]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-fa7799d5]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-fa7799d5]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-fa7799d5]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-fa7799d5]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-fa7799d5]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-8426fc1a]{display:none}.dark .VPImage.light[data-v-8426fc1a]{display:none}.VPHero[data-v-4f9c455b]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-4f9c455b]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-4f9c455b]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-4f9c455b]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-4f9c455b]{flex-direction:row}}.main[data-v-4f9c455b]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-4f9c455b]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-4f9c455b]{text-align:left}}@media (min-width: 960px){.main[data-v-4f9c455b]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-4f9c455b]{max-width:592px}}.heading[data-v-4f9c455b]{display:flex;flex-direction:column}.name[data-v-4f9c455b],.text[data-v-4f9c455b]{width:fit-content;max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-4f9c455b],.VPHero.has-image .text[data-v-4f9c455b]{margin:0 auto}.name[data-v-4f9c455b]{color:var(--vp-home-hero-name-color)}.clip[data-v-4f9c455b]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-4f9c455b],.text[data-v-4f9c455b]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-4f9c455b],.text[data-v-4f9c455b]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-4f9c455b],.VPHero.has-image .text[data-v-4f9c455b]{margin:0}}.tagline[data-v-4f9c455b]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-4f9c455b]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-4f9c455b]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-4f9c455b]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-4f9c455b]{margin:0}}.actions[data-v-4f9c455b]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-4f9c455b]{justify-content:center}@media (min-width: 640px){.actions[data-v-4f9c455b]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-4f9c455b]{justify-content:flex-start}}.action[data-v-4f9c455b]{flex-shrink:0;padding:6px}.image[data-v-4f9c455b]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-4f9c455b]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-4f9c455b]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-4f9c455b]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-4f9c455b]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-4f9c455b]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-4f9c455b]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-4f9c455b]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-4f9c455b]{width:320px;height:320px}}[data-v-4f9c455b] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-4f9c455b] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-4f9c455b] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-a3976bdc]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-a3976bdc]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-a3976bdc]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-a3976bdc]>.VPImage{margin-bottom:20px}.icon[data-v-a3976bdc]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-a3976bdc]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-a3976bdc]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-a3976bdc]{padding-top:8px}.link-text-value[data-v-a3976bdc]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-a3976bdc]{margin-left:6px}.VPFeatures[data-v-a6181336]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-a6181336]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-a6181336]{padding:0 64px}}.container[data-v-a6181336]{margin:0 auto;max-width:1152px}.items[data-v-a6181336]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-a6181336]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-a6181336],.item.grid-4[data-v-a6181336]{width:50%}.item.grid-3[data-v-a6181336],.item.grid-6[data-v-a6181336]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-a6181336]{width:25%}}.container[data-v-8e2d4988]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-8e2d4988]{padding:0 48px}}@media (min-width: 960px){.container[data-v-8e2d4988]{width:100%;padding:0 64px}}.vp-doc[data-v-8e2d4988] .VPHomeSponsors,.vp-doc[data-v-8e2d4988] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-8e2d4988] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-8e2d4988] .VPHomeSponsors a,.vp-doc[data-v-8e2d4988] .VPTeamPage a{text-decoration:none}.VPHome[data-v-8b561e3d]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-8b561e3d]{margin-bottom:128px}}.VPContent[data-v-1428d186]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-1428d186]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-1428d186]{margin:0}@media (min-width: 960px){.VPContent[data-v-1428d186]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-1428d186]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-1428d186]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-e315a0ad]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-e315a0ad]{display:none}.VPFooter[data-v-e315a0ad] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-e315a0ad] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-e315a0ad]{padding:32px}}.container[data-v-e315a0ad]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-e315a0ad],.copyright[data-v-e315a0ad]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-8a42e2b4]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-8a42e2b4]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-8a42e2b4]{color:var(--vp-c-text-1)}.icon[data-v-8a42e2b4]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-8a42e2b4]{font-size:14px}.icon[data-v-8a42e2b4]{font-size:16px}}.open>.icon[data-v-8a42e2b4]{transform:rotate(90deg)}.items[data-v-8a42e2b4]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-8a42e2b4]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-8a42e2b4]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-8a42e2b4]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-8a42e2b4]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-8a42e2b4]{transition:all .2s ease-out}.flyout-leave-active[data-v-8a42e2b4]{transition:all .15s ease-in}.flyout-enter-from[data-v-8a42e2b4],.flyout-leave-to[data-v-8a42e2b4]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-a6f0e41e]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-a6f0e41e]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-a6f0e41e]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-a6f0e41e]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-a6f0e41e]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-a6f0e41e]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-a6f0e41e]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-a6f0e41e]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-a6f0e41e]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-a6f0e41e]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-a6f0e41e]{display:none}}.menu-icon[data-v-a6f0e41e]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-a6f0e41e]{padding:12px 32px 11px}}.VPSwitch[data-v-1d5665e3]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-1d5665e3]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-1d5665e3]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-1d5665e3]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-1d5665e3] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-1d5665e3] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-5337faa4]{opacity:1}.moon[data-v-5337faa4],.dark .sun[data-v-5337faa4]{opacity:0}.dark .moon[data-v-5337faa4]{opacity:1}.dark .VPSwitchAppearance[data-v-5337faa4] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-6c893767]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-6c893767]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-35975db6]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-35975db6]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-35975db6]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-35975db6]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-69e747b5]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-69e747b5]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-69e747b5]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-69e747b5]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-b98bc113]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-b98bc113] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-b98bc113] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-b98bc113] .group:last-child{padding-bottom:0}.VPMenu[data-v-b98bc113] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-b98bc113] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-b98bc113] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-b98bc113] .action{padding-left:24px}.VPFlyout[data-v-cf11d7a2]{position:relative}.VPFlyout[data-v-cf11d7a2]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-cf11d7a2]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-cf11d7a2]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-cf11d7a2]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-cf11d7a2]{color:var(--vp-c-brand-2)}.button[aria-expanded=false]+.menu[data-v-cf11d7a2]{opacity:0;visibility:hidden;transform:translateY(0)}.VPFlyout:hover .menu[data-v-cf11d7a2],.button[aria-expanded=true]+.menu[data-v-cf11d7a2]{opacity:1;visibility:visible;transform:translateY(0)}.button[data-v-cf11d7a2]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-cf11d7a2]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-cf11d7a2]{margin-right:0;font-size:16px}.text-icon[data-v-cf11d7a2]{margin-left:4px;font-size:14px}.icon[data-v-cf11d7a2]{font-size:20px;transition:fill .25s}.menu[data-v-cf11d7a2]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-bd121fe5]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-bd121fe5]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-bd121fe5]>svg,.VPSocialLink[data-v-bd121fe5]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-7bc22406]{display:flex;justify-content:center}.VPNavBarExtra[data-v-bb2aa2f0]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-bb2aa2f0]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-bb2aa2f0]{display:none}}.trans-title[data-v-bb2aa2f0]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-bb2aa2f0],.item.social-links[data-v-bb2aa2f0]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-bb2aa2f0]{min-width:176px}.appearance-action[data-v-bb2aa2f0]{margin-right:-2px}.social-links-list[data-v-bb2aa2f0]{margin:-4px -8px}.VPNavBarHamburger[data-v-e5dd9c1c]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-e5dd9c1c]{display:none}}.container[data-v-e5dd9c1c]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-e5dd9c1c]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-e5dd9c1c]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .middle[data-v-e5dd9c1c],.VPNavBarHamburger.active:hover .bottom[data-v-e5dd9c1c]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-e5dd9c1c],.middle[data-v-e5dd9c1c],.bottom[data-v-e5dd9c1c]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-e5dd9c1c]{top:0;left:0;transform:translate(0)}.middle[data-v-e5dd9c1c]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-e5dd9c1c]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-e56f3d57]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-e56f3d57],.VPNavBarMenuLink[data-v-e56f3d57]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-dc692963]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-dc692963]{display:flex}}/*! @docsearch/css 3.8.2 | MIT License | © Algolia, Inc. and contributors | https://docsearch.algolia.com */:root{--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 1px 0 rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12)}html[data-theme=dark]{--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-key-pressed-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 1px 1px 0 #0304094d;--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}.DocSearch-Button{align-items:center;background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;display:flex;font-weight:500;height:36px;justify-content:space-between;margin:0 0 0 16px;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:none}.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch-Button-Key--pressed{box-shadow:var(--docsearch-key-pressed-shadow);transform:translate3d(0,1px,0)}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder{display:none}}.DocSearch--active{overflow:hidden!important}.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Container a{text-decoration:none}.DocSearch-Link{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;font:inherit;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:var(--docsearch-text-color);flex:1;font:inherit;font-size:1.2em;height:100%;outline:none;padding:0 0 0 8px;width:80%}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator{display:none}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{animation:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0;stroke-width:var(--docsearch-icon-stroke-width)}}.DocSearch-Reset{animation:fade-in .1s ease-in forwards;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;padding:2px;right:0;stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Cancel{display:none}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:transparent}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{color:var(--docsearch-muted-color);display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--deleting{transition:none}}.DocSearch-Hit--deleting{opacity:0;transition:all .25s linear}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit--favoriting{transition:none}}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:all .25s linear;transition-delay:.25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;stroke-width:var(--docsearch-icon-stroke-width);width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color);stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:inherit;cursor:pointer;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{transition:none}}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:none;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}.DocSearch-VisuallyHiddenForAccessibility{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}@media (max-width:768px){:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh, 1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Dropdown{max-height:calc(var(--docsearch-vh, 1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Cancel{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:none;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}[class*=DocSearch]{--docsearch-primary-color: var(--vp-c-brand-1);--docsearch-highlight-color: var(--docsearch-primary-color);--docsearch-text-color: var(--vp-c-text-1);--docsearch-muted-color: var(--vp-c-text-2);--docsearch-searchbox-shadow: none;--docsearch-searchbox-background: transparent;--docsearch-searchbox-focus-background: transparent;--docsearch-key-gradient: transparent;--docsearch-key-shadow: none;--docsearch-modal-background: var(--vp-c-bg-soft);--docsearch-footer-background: var(--vp-c-bg)}.dark [class*=DocSearch]{--docsearch-modal-shadow: none;--docsearch-footer-shadow: none;--docsearch-logo-color: var(--vp-c-text-2);--docsearch-hit-background: var(--vp-c-default-soft);--docsearch-hit-color: var(--vp-c-text-2);--docsearch-hit-shadow: none}.DocSearch-Button{display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:48px;height:55px;background:transparent;transition:border-color .25s}.DocSearch-Button:hover{background:transparent}.DocSearch-Button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.DocSearch-Button-Key--pressed{transform:none;box-shadow:none}.DocSearch-Button:focus:not(:focus-visible){outline:none!important}@media (min-width: 768px){.DocSearch-Button{justify-content:flex-start;border:1px solid transparent;border-radius:8px;padding:0 10px 0 12px;width:100%;height:40px;background-color:var(--vp-c-bg-alt)}.DocSearch-Button:hover{border-color:var(--vp-c-brand-1);background:var(--vp-c-bg-alt)}}.DocSearch-Button .DocSearch-Button-Container{display:flex;align-items:center}.DocSearch-Button .DocSearch-Search-Icon{position:relative;width:16px;height:16px;color:var(--vp-c-text-1);fill:currentColor;transition:color .5s}.DocSearch-Button:hover .DocSearch-Search-Icon{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Search-Icon{top:1px;margin-right:8px;width:14px;height:14px;color:var(--vp-c-text-2)}}.DocSearch-Button .DocSearch-Button-Placeholder{display:none;margin-top:2px;padding:0 16px 0 0;font-size:13px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.DocSearch-Button:hover .DocSearch-Button-Placeholder{color:var(--vp-c-text-1)}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Placeholder{display:inline-block}}.DocSearch-Button .DocSearch-Button-Keys{direction:ltr;display:none;min-width:auto}@media (min-width: 768px){.DocSearch-Button .DocSearch-Button-Keys{display:flex;align-items:center}}.DocSearch-Button .DocSearch-Button-Key{display:block;margin:2px 0 0;border:1px solid var(--vp-c-divider);border-right:none;border-radius:4px 0 0 4px;padding-left:6px;min-width:0;width:auto;height:22px;line-height:22px;font-family:var(--vp-font-family-base);font-size:12px;font-weight:500;transition:color .5s,border-color .5s}.DocSearch-Button .DocSearch-Button-Key+.DocSearch-Button-Key{border-right:1px solid var(--vp-c-divider);border-left:none;border-radius:0 4px 4px 0;padding-left:2px;padding-right:6px}.DocSearch-Button .DocSearch-Button-Key:first-child{font-size:0!important}.DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"Ctrl";font-size:12px;letter-spacing:normal;color:var(--docsearch-muted-color)}.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after{content:"⌘"}.DocSearch-Button .DocSearch-Button-Key:first-child>*{display:none}.DocSearch-Search-Icon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke-width='1.6' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' d='m14.386 14.386 4.088 4.088-4.088-4.088A7.533 7.533 0 1 1 3.733 3.733a7.533 7.533 0 0 1 10.653 10.653z'/%3E%3C/svg%3E")}.VPNavBarSearch{display:flex;align-items:center}@media (min-width: 768px){.VPNavBarSearch{flex-grow:1;padding-left:24px}}@media (min-width: 960px){.VPNavBarSearch{padding-left:32px}}.dark .DocSearch-Footer{border-top:1px solid var(--vp-c-divider)}.DocSearch-Form{border:1px solid var(--vp-c-brand-1);background-color:var(--vp-c-white)}.dark .DocSearch-Form{background-color:var(--vp-c-default-soft)}.DocSearch-Screen-Icon>svg{margin:auto}.VPNavBarSocialLinks[data-v-0394ad82]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-0394ad82]{display:flex;align-items:center}}.title[data-v-1168a8e4]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-1168a8e4]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-1168a8e4]{border-bottom-color:var(--vp-c-divider)}}[data-v-1168a8e4] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-88af2de4]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-88af2de4]{display:flex;align-items:center}}.title[data-v-88af2de4]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-6aa21345]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-6aa21345]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-6aa21345]:not(.home){background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar[data-v-6aa21345]:not(.home){background-color:transparent}.VPNavBar[data-v-6aa21345]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-6aa21345]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-6aa21345]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-6aa21345]{padding:0}}.container[data-v-6aa21345]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-6aa21345],.container>.content[data-v-6aa21345]{pointer-events:none}.container[data-v-6aa21345] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-6aa21345]{max-width:100%}}.title[data-v-6aa21345]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-6aa21345]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-6aa21345]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-6aa21345]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-6aa21345]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-6aa21345]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-6aa21345]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.home.top) .content-body[data-v-6aa21345]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-6aa21345]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-6aa21345]{column-gap:.5rem}}.menu+.translations[data-v-6aa21345]:before,.menu+.appearance[data-v-6aa21345]:before,.menu+.social-links[data-v-6aa21345]:before,.translations+.appearance[data-v-6aa21345]:before,.appearance+.social-links[data-v-6aa21345]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-6aa21345]:before,.translations+.appearance[data-v-6aa21345]:before{margin-right:16px}.appearance+.social-links[data-v-6aa21345]:before{margin-left:16px}.social-links[data-v-6aa21345]{margin-right:-8px}.divider[data-v-6aa21345]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-6aa21345]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-6aa21345]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-6aa21345]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-6aa21345]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.home.top) .divider-line[data-v-6aa21345]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-6aa21345]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-b44890b2]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-b44890b2]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-df37e6dd]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-df37e6dd]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-3e9c20e4]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-3e9c20e4]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-8133b170]{display:block}.title[data-v-8133b170]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-b9ab8c58]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-b9ab8c58]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-b9ab8c58]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-b9ab8c58]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-b9ab8c58]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-b9ab8c58]{transform:rotate(45deg)}.button[data-v-b9ab8c58]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-b9ab8c58]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-b9ab8c58]{transition:transform .25s}.group[data-v-b9ab8c58]:first-child{padding-top:0}.group+.group[data-v-b9ab8c58],.group+.item[data-v-b9ab8c58]{padding-top:4px}.VPNavScreenTranslations[data-v-858fe1a4]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-858fe1a4]{height:auto}.title[data-v-858fe1a4]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-858fe1a4]{font-size:16px}.icon.lang[data-v-858fe1a4]{margin-right:8px}.icon.chevron[data-v-858fe1a4]{margin-left:4px}.list[data-v-858fe1a4]{padding:4px 0 0 24px}.link[data-v-858fe1a4]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-f2779853]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-f2779853],.VPNavScreen.fade-leave-active[data-v-f2779853]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-f2779853],.VPNavScreen.fade-leave-active .container[data-v-f2779853]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-f2779853],.VPNavScreen.fade-leave-to[data-v-f2779853]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-f2779853],.VPNavScreen.fade-leave-to .container[data-v-f2779853]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-f2779853]{display:none}}.container[data-v-f2779853]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-f2779853],.menu+.appearance[data-v-f2779853],.translations+.appearance[data-v-f2779853]{margin-top:24px}.menu+.social-links[data-v-f2779853]{margin-top:16px}.appearance+.social-links[data-v-f2779853]{margin-top:16px}.VPNav[data-v-ae24b3ad]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-ae24b3ad]{position:fixed}}.VPSidebarItem.level-0[data-v-b3fd67f8]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-b3fd67f8]{padding-bottom:10px}.item[data-v-b3fd67f8]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-b3fd67f8]{cursor:pointer}.indicator[data-v-b3fd67f8]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-b3fd67f8],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-b3fd67f8]{background-color:var(--vp-c-brand-1)}.link[data-v-b3fd67f8]{display:flex;align-items:center;flex-grow:1}.text[data-v-b3fd67f8]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-b3fd67f8]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-b3fd67f8],.VPSidebarItem.level-2 .text[data-v-b3fd67f8],.VPSidebarItem.level-3 .text[data-v-b3fd67f8],.VPSidebarItem.level-4 .text[data-v-b3fd67f8],.VPSidebarItem.level-5 .text[data-v-b3fd67f8]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-b3fd67f8],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-b3fd67f8]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.has-active>.item>.text[data-v-b3fd67f8],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-b3fd67f8]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-b3fd67f8],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-b3fd67f8]{color:var(--vp-c-brand-1)}.caret[data-v-b3fd67f8]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-b3fd67f8]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-b3fd67f8]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-b3fd67f8]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-b3fd67f8]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-b3fd67f8],.VPSidebarItem.level-2 .items[data-v-b3fd67f8],.VPSidebarItem.level-3 .items[data-v-b3fd67f8],.VPSidebarItem.level-4 .items[data-v-b3fd67f8],.VPSidebarItem.level-5 .items[data-v-b3fd67f8]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-b3fd67f8]{display:none}.no-transition[data-v-c40bc020] .caret-icon{transition:none}.group+.group[data-v-c40bc020]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-c40bc020]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-319d5ca6]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-319d5ca6]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-319d5ca6]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-319d5ca6]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-319d5ca6]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-319d5ca6]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-319d5ca6]{outline:0}.VPSkipLink[data-v-0b0ada53]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-0b0ada53]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-0b0ada53]{top:14px;left:16px}}.Layout[data-v-5d98c3a5]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-3d121b4a]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPHomeSponsors[data-v-3d121b4a]{margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{margin:128px 0}}.VPHomeSponsors[data-v-3d121b4a]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-3d121b4a]{padding:0 64px}}.container[data-v-3d121b4a]{margin:0 auto;max-width:1152px}.love[data-v-3d121b4a]{margin:0 auto;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-3d121b4a]{display:inline-block}.message[data-v-3d121b4a]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-3d121b4a]{padding-top:32px}.action[data-v-3d121b4a]{padding-top:40px;text-align:center}.VPTeamMembersItem[data-v-f3fa364a]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-f3fa364a]{padding:32px}.VPTeamMembersItem.small .data[data-v-f3fa364a]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-f3fa364a]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-f3fa364a]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-f3fa364a]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-f3fa364a]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-f3fa364a]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-f3fa364a]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-f3fa364a]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-f3fa364a]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-f3fa364a]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-f3fa364a]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-f3fa364a]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-f3fa364a]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-f3fa364a]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-f3fa364a]{text-align:center}.avatar[data-v-f3fa364a]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-f3fa364a]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;object-fit:cover}.name[data-v-f3fa364a]{margin:0;font-weight:600}.affiliation[data-v-f3fa364a]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-f3fa364a]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-f3fa364a]:hover{color:var(--vp-c-brand-1)}.desc[data-v-f3fa364a]{margin:0 auto}.desc[data-v-f3fa364a] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-f3fa364a]{display:flex;justify-content:center;height:56px}.sp-link[data-v-f3fa364a]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-f3fa364a]:hover,.sp .sp-link.link[data-v-f3fa364a]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-f3fa364a]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-6cb0dbc4]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-6cb0dbc4]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-6cb0dbc4]{max-width:876px}.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-6cb0dbc4]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-6cb0dbc4]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-6cb0dbc4]{max-width:760px}.container[data-v-6cb0dbc4]{display:grid;gap:24px;margin:0 auto;max-width:1152px}.VPTeamPage[data-v-7c57f839]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-7c57f839]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-7c57f839-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-7c57f839-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-7c57f839-s],.VPTeamMembers+.VPTeamPageSection[data-v-7c57f839-s]{margin-top:96px}}.VPTeamMembers[data-v-7c57f839-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-7c57f839-s]{padding:0 64px}}.VPTeamPageSection[data-v-b1a88750]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-b1a88750]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-b1a88750]{padding:0 64px}}.title[data-v-b1a88750]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-b1a88750]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-b1a88750]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-b1a88750]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-b1a88750]{padding-top:40px}.VPTeamPageTitle[data-v-bf2cbdac]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-bf2cbdac]{padding:80px 64px 48px}}.title[data-v-bf2cbdac]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-bf2cbdac]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-bf2cbdac]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-bf2cbdac]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff)} diff --git a/docs/.vitepress/dist/guide/architecture.html b/docs/.vitepress/dist/guide/architecture.html new file mode 100644 index 0000000..8a59876 --- /dev/null +++ b/docs/.vitepress/dist/guide/architecture.html @@ -0,0 +1,45 @@ + + + + + + Architecture | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Architecture

EmptyGraph follows a strict Hexagonal Architecture (Ports & Adapters).

The Hexagon

mermaid
flowchart TD
+  User --> EG[EmptyGraph Facade]
+  EG --> GS[GraphService]
+  EG --> TS[TraversalService]
+  
+  GS --> Ports
+  TS --> Ports
+  
+  subgraph Ports
+    GPP[GraphPersistencePort]
+    ISP[IndexStoragePort]
+  end
+  
+  subgraph Adapters
+    Ports --> GGA[GitGraphAdapter]
+  end
+  
+  GGA --> Git[Git Plumbing]

Components

  • Domain Layer: Pure logic. GraphService manages nodes, TraversalService manages walking the graph.
  • Ports Layer: Interfaces that define how we talk to the outside world.
  • Adapters Layer: The implementation. GitGraphAdapter translates our domain calls into git CLI commands.

Why this matters

This decoupling means the "Brain" (Traversal) doesn't know it's running on Git. It just asks for "neighbors." This allowed us to swap in the Bitmap Index without changing the traversal algorithms.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/guide/core-concepts.html b/docs/.vitepress/dist/guide/core-concepts.html new file mode 100644 index 0000000..8b13c52 --- /dev/null +++ b/docs/.vitepress/dist/guide/core-concepts.html @@ -0,0 +1,28 @@ + + + + + + Core Concepts | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Core Concepts

To understand EmptyGraph, you need to understand three things: Nodes, Edges, and the Index.

1. The Node (A Ghost Commit)

A Node is just a Git Commit.

  • ID: The SHA-1 hash of the commit.
  • Data: The commit message (String/JSON).
  • Metadata: Author, Committer, Date.

Crucially, the commit points to the Empty Tree. This means it has no file content. It is a "Ghost" commit.

2. The Edge (Parent Pointers)

An Edge is the relationship between commits.

  • Git natively supports Backward Edges (Child points to Parent).
  • This creates a Directed Acyclic Graph (DAG).

3. The Index (The Cheat Code)

Git does not support Forward Edges (Parent points to Children). To find children, you have to scan the whole repo.

EmptyGraph solves this with a Roaring Bitmap Index.

  • We assign every SHA an integer ID.
  • We store adjacency lists in compressed bitmaps.
  • We save this index back into Git as a set of sharded JSON files.

When you ask graph.getChildren(parentSha), we check the index (O(1)). When you ask graph.getParents(childSha), we check the index (O(1)).

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/guide/getting-started.html b/docs/.vitepress/dist/guide/getting-started.html new file mode 100644 index 0000000..6e2997e --- /dev/null +++ b/docs/.vitepress/dist/guide/getting-started.html @@ -0,0 +1,61 @@ + + + + + + Getting Started | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Getting Started

Ready to perform some stunts?

Installation

bash
npm install @git-stunts/empty-graph @git-stunts/plumbing

The 30-Second Setup

You need two things:

  1. Plumbing: To talk to Git.
  2. Adapter: To translate Git to Graph.
javascript
import GitPlumbing from '@git-stunts/plumbing';
+import EmptyGraph, { GitGraphAdapter } from '@git-stunts/empty-graph';
+
+// 1. Point to a directory (it will be `git init`'d automatically if needed)
+const plumbing = new GitPlumbing({ cwd: './my-ghost-db' });
+
+// 2. Create the adapter
+const persistence = new GitGraphAdapter({ plumbing });
+
+// 3. Initialize the Graph
+const graph = new EmptyGraph({ persistence });
+
+// 4. Create your first Invisible Node
+const sha = await graph.createNode({
+  message: JSON.stringify({
+    type: 'Genesis',
+    payload: 'Hello from the other side'
+  })
+});
+
+console.log(`Created node: ${sha}`);

Reading it back

You can read by SHA, or iterate through history.

javascript
// Direct Read (O(1))
+const data = await graph.readNode(sha);
+
+// Stream History
+for await (const node of graph.iterateNodes({ ref: sha })) {
+  console.log(node.message);
+}

Enabling the "Supercharger" (Bitmap Index)

By default, we just use Git. But if you want to find children (traverse forward) instantly, you need the index.

javascript
// Build the index (scans history and saves a binary tree to git)
+const indexOid = await graph.rebuildIndex(sha);
+
+// Load it for O(1) powers
+await graph.loadIndex(indexOid);
+
+// Now you can look into the future
+const children = await graph.getChildren(sha);

Next Steps

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/guide/what-is-this.html b/docs/.vitepress/dist/guide/what-is-this.html new file mode 100644 index 0000000..62372ae --- /dev/null +++ b/docs/.vitepress/dist/guide/what-is-this.html @@ -0,0 +1,28 @@ + + + + + + What is this? | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

What is this?

EmptyGraph is a graph database that subverts Git's internal object model to store structured data invisibly.

It is a Git Stunt: a solution so unorthodox that if Linus Torvalds saw it, he would stop what he was doing, remove his glasses, rub his exhausted eyes, sigh deeply, and then, after a long silence, mutter: "You know what? Have fun," shake his head, and walk away.

The Core Subversion

Git is usually used to track files. EmptyGraph subverts this by using Git's Directed Acyclic Graph (DAG) to store structured data in the commits themselves.

Because all commits point to the "Empty Tree" (4b825dc642cb6eb9a060e54bf8d69288fbee4904), your data does not exist as files in the working directory—it exists entirely within the Git object database.

Why do this?

If you’re looking for the most "practical" way to build a database, you’d reach for Postgres. But the goal here isn't conventional efficiency; it’s first-principles engineering.

When we use Git to perform these "stunts," we accidentally inherit properties that take months to build into a standard SQL-based app:

  • Offline-First Synchronization: Git's distributed model handles replication for free.
  • Cryptographic Non-Repudiation: Every node's SHA proves its integrity and ancestry.
  • Universal Tooling: Use git log, git show, and git branch to inspect your database.
  • Infinite Point-in-Time Recovery: The reflog ensures you never truly lose a "deleted" node.

The Performance "Stunt"

Git is terrible at "future" lookups (finding children of a parent). To fix this, EmptyGraph builds a Secondary Roaring Bitmap Index.

This index provides O(1) lookups in both directions, making it 10,000x faster than raw Git traversal for complex graph queries, while still storing that index back into Git as a series of sharded blobs.

Is this production ready?

EmptyGraph is a stunt, not a product.

It's proof that Git's data model is more powerful than people realize. It's a legitimate tool for specific use cases (like AI agent memory or audit trails), but it's not a replacement for purpose-built graph databases like Neo4j if you need ACID transactions or multi-user row-level security.

Use it when Git's properties align with your needs. Don't use it just because it's clever.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/hashmap.json b/docs/.vitepress/dist/hashmap.json new file mode 100644 index 0000000..1d36874 --- /dev/null +++ b/docs/.vitepress/dist/hashmap.json @@ -0,0 +1 @@ +{"api_bitmap-index.md":"DsG7ME_t","api_empty-graph.md":"m8YhdPmC","api_graph-service.md":"w4rOehRM","api_index.md":"seH7UXM8","api_traversal-service.md":"B5EG-8W-","guide_architecture.md":"CZgLXfX4","guide_core-concepts.md":"BOais_2r","guide_getting-started.md":"CjJfG1lj","guide_what-is-this.md":"DGkKwESk","images_bitmap-index.md":"CS_4KAjN","index.md":"BV983U1U","internals_bitmap-index.md":"C00etvr2","internals_plumbing.md":"CODhq3GG","stunts_event-sourcing.md":"hd1e6A6k","stunts_invisible-storage.md":"CtCpDpSQ","stunts_lagrangian-routing.md":"DmVl5Oa4","stunts_streaming.md":"BzupMMFw"} diff --git a/docs/.vitepress/dist/images/bitmap-index.html b/docs/.vitepress/dist/images/bitmap-index.html new file mode 100644 index 0000000..8ce16be --- /dev/null +++ b/docs/.vitepress/dist/images/bitmap-index.html @@ -0,0 +1,262 @@ + + + + + + Roaring Bitmap Index Architecture | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Roaring Bitmap Index Architecture

This diagram illustrates how EMPTY GRAPH uses Roaring Bitmaps to provide O(1) lookups for graph traversal operations.

Overview Diagram

mermaid
flowchart TB
+    subgraph GRAPH["Git Commit Graph"]
+        direction TB
+        A["Node A<br/>(root commit)"]
+        B["Node B<br/>(branch 1)"]
+        C["Node C<br/>(branch 2)"]
+        D["Node D<br/>(merge commit)"]
+
+        A --> B
+        A --> C
+        B --> D
+        C --> D
+    end
+
+    subgraph INDEX["Bitmap Index Structure"]
+        direction TB
+
+        subgraph SHA_TO_ID["SHA to ID Mapping"]
+            M1["meta_a1.json<br/>{ 'a1b2c3...': 0 }"]
+            M2["meta_b2.json<br/>{ 'b2c3d4...': 1 }"]
+            M3["meta_c3.json<br/>{ 'c3d4e5...': 2 }"]
+            M4["meta_d4.json<br/>{ 'd4e5f6...': 3 }"]
+        end
+
+        subgraph FWD["Forward Index (fwd)<br/>parent -> children IDs"]
+            F1["shards_fwd_a1.json<br/>A: bitmap{1, 2}"]
+            F2["shards_fwd_b2.json<br/>B: bitmap{3}"]
+            F3["shards_fwd_c3.json<br/>C: bitmap{3}"]
+        end
+
+        subgraph REV["Reverse Index (rev)<br/>child -> parent IDs"]
+            R2["shards_rev_b2.json<br/>B: bitmap{0}"]
+            R3["shards_rev_c3.json<br/>C: bitmap{0}"]
+            R4["shards_rev_d4.json<br/>D: bitmap{1, 2}"]
+        end
+    end
+
+    GRAPH -.->|"Build Index"| INDEX

SHA to Numeric ID Mapping

SHAs are mapped to compact numeric IDs for efficient bitmap storage:

mermaid
flowchart LR
+    subgraph SHAs["40-char Git SHAs"]
+        SHA_A["a1b2c3d4e5..."]
+        SHA_B["b2c3d4e5f6..."]
+        SHA_C["c3d4e5f6a7..."]
+        SHA_D["d4e5f6a7b8..."]
+    end
+
+    subgraph IDs["Numeric IDs"]
+        ID0["0"]
+        ID1["1"]
+        ID2["2"]
+        ID3["3"]
+    end
+
+    SHA_A --> ID0
+    SHA_B --> ID1
+    SHA_C --> ID2
+    SHA_D --> ID3
+
+    style ID0 fill:#e1f5fe
+    style ID1 fill:#e1f5fe
+    style ID2 fill:#e1f5fe
+    style ID3 fill:#e1f5fe

Query Flow: getChildren(A)

mermaid
sequenceDiagram
+    participant User
+    participant Reader as BitmapIndexReader
+    participant Meta as meta_a1.json
+    participant Fwd as shards_fwd_a1.json
+    participant Bitmap as RoaringBitmap32
+
+    User->>Reader: getChildren("a1b2c3...")
+
+    Note over Reader: 1. Extract SHA prefix "a1"
+
+    Reader->>Fwd: Load shard (lazy, cached)
+    Fwd-->>Reader: { "a1b2c3...": "base64bitmap" }
+
+    Note over Reader: 2. Decode bitmap for SHA
+
+    Reader->>Bitmap: deserialize(base64)
+    Bitmap-->>Reader: bitmap{1, 2}
+
+    Note over Reader: 3. Convert IDs to SHAs
+
+    Reader->>Meta: Load all meta shards (cached)
+    Meta-->>Reader: ID 1 = "b2c3d4...", ID 2 = "c3d4e5..."
+
+    Reader-->>User: ["b2c3d4...", "c3d4e5..."]
+
+    Note over User,Reader: O(1) lookup via bitmap!

Warning: First query loads all meta shards O(n); subsequent queries O(1)

BitmapIndexReader.getChildren depends on _buildIdToShaMapping which loads all meta shards (up to 256) on the first query. Only subsequent lookups are O(1). Note that the LRU cache (default 100) can be exceeded during initial load.

Query Flow: getParents(D)

mermaid
sequenceDiagram
+    participant User
+    participant Reader as BitmapIndexReader
+    participant Rev as shards_rev_d4.json
+    participant Bitmap as RoaringBitmap32
+    participant Meta as meta_*.json
+
+    User->>Reader: getParents("d4e5f6...")
+
+    Note over Reader: 1. Extract SHA prefix "d4"
+
+    Reader->>Rev: Load reverse shard (lazy, cached)
+    Rev-->>Reader: { "d4e5f6...": "base64bitmap" }
+
+    Note over Reader: 2. Decode bitmap for SHA
+
+    Reader->>Bitmap: deserialize(base64)
+    Bitmap-->>Reader: bitmap{1, 2}
+
+    Note over Reader: 3. Convert IDs to SHAs
+
+    Reader->>Meta: Lookup IDs 1 and 2
+    Meta-->>Reader: ID 1 = "b2c3d4...", ID 2 = "c3d4e5..."
+
+    Reader-->>User: ["b2c3d4...", "c3d4e5..."]
+
+    Note over User,Reader: Merge commits with multiple<br/>parents resolved in O(1)!

Sharding Strategy

Shards are organized by 2-character SHA prefix for efficient lazy loading:

mermaid
flowchart TB
+    subgraph Storage["Index Storage (256 possible prefixes)"]
+        direction LR
+
+        subgraph Prefix_00["Prefix '00'"]
+            meta_00["meta_00.json"]
+            fwd_00["shards_fwd_00.json"]
+            rev_00["shards_rev_00.json"]
+        end
+
+        subgraph Prefix_a1["Prefix 'a1'"]
+            meta_a1["meta_a1.json"]
+            fwd_a1["shards_fwd_a1.json"]
+            rev_a1["shards_rev_a1.json"]
+        end
+
+        subgraph Prefix_ff["Prefix 'ff'"]
+            meta_ff["meta_ff.json"]
+            fwd_ff["shards_fwd_ff.json"]
+            rev_ff["shards_rev_ff.json"]
+        end
+
+        dots["..."]
+    end
+
+    subgraph Query["Query: getChildren('a1b2c3...')"]
+        Q1["1. Extract prefix 'a1'"]
+        Q2["2. Load only shards_fwd_a1.json"]
+        Q3["3. Other shards stay unloaded"]
+    end
+
+    Query --> Prefix_a1
+
+    style Prefix_a1 fill:#c8e6c9
+    style Prefix_00 fill:#f5f5f5
+    style Prefix_ff fill:#f5f5f5

Why Roaring Bitmaps Are Fast

mermaid
flowchart TB
+    subgraph Traditional["Traditional Approach"]
+        direction TB
+        T1["Store edges as arrays"]
+        T2["children: ['sha1', 'sha2', ...]"]
+        T3["O(n) to check membership"]
+        T4["Large storage for many edges"]
+
+        T1 --> T2 --> T3 --> T4
+    end
+
+    subgraph Roaring["Roaring Bitmap Approach"]
+        direction TB
+        R1["Store IDs in compressed bitmap"]
+        R2["children: bitmap{1, 2, 3, ...}"]
+        R3["O(1) to check membership"]
+        R4["Highly compressed storage"]
+
+        R1 --> R2 --> R3 --> R4
+    end
+
+    subgraph Benefits["Key Benefits"]
+        B1["Compression: Run-length encoding for dense ranges"]
+        B2["Fast Operations: AND, OR, XOR on bitmaps"]
+        B3["Memory Efficient: 10-100x smaller than arrays"]
+        B4["Lazy Loading: Only load shards you need"]
+    end
+
+    Traditional -.->|"vs"| Roaring
+    Roaring --> Benefits
+
+    style Roaring fill:#e8f5e9
+    style Traditional fill:#ffebee
+    style Benefits fill:#e3f2fd

Complete Index Structure Example

mermaid
flowchart TB
+    subgraph Graph["Example Git Graph"]
+        A["A (id=0)<br/>sha: a1b2c3..."]
+        B["B (id=1)<br/>sha: b2c3d4..."]
+        C["C (id=2)<br/>sha: c3d4e5..."]
+        D["D (id=3)<br/>sha: d4e5f6..."]
+
+        A -->|"parent"| B
+        A -->|"parent"| C
+        B -->|"parent"| D
+        C -->|"parent"| D
+    end
+
+    subgraph Forward["Forward Index (fwd)<br/>Who are my children?"]
+        FWD_A["A -> bitmap{1, 2}<br/>(children: B, C)"]
+        FWD_B["B -> bitmap{3}<br/>(child: D)"]
+        FWD_C["C -> bitmap{3}<br/>(child: D)"]
+        FWD_D["D -> bitmap{}<br/>(no children)"]
+    end
+
+    subgraph Reverse["Reverse Index (rev)<br/>Who are my parents?"]
+        REV_A["A -> bitmap{}<br/>(no parents - root)"]
+        REV_B["B -> bitmap{0}<br/>(parent: A)"]
+        REV_C["C -> bitmap{0}<br/>(parent: A)"]
+        REV_D["D -> bitmap{1, 2}<br/>(parents: B, C)"]
+    end
+
+    Graph --> Forward
+    Graph --> Reverse
+
+    style FWD_A fill:#bbdefb
+    style FWD_B fill:#bbdefb
+    style FWD_C fill:#bbdefb
+    style FWD_D fill:#bbdefb
+    style REV_A fill:#c8e6c9
+    style REV_B fill:#c8e6c9
+    style REV_C fill:#c8e6c9
+    style REV_D fill:#c8e6c9

Shard File Format

Each shard file contains a versioned envelope with checksum for integrity:

mermaid
flowchart TB
+    subgraph Envelope["Shard Envelope"]
+        direction TB
+        V["version: 1"]
+        C["checksum: 'sha256...'"]
+        D["data: {...}"]
+    end
+
+    subgraph MetaShard["meta_a1.json"]
+        MD["data: {<br/>  'a1b2c3...': 0,<br/>  'a1f2e3...': 42,<br/>  ...<br/>}"]
+    end
+
+    subgraph BitmapShard["shards_fwd_a1.json"]
+        BD["data: {<br/>  'a1b2c3...': 'base64bitmap',<br/>  'a1f2e3...': 'base64bitmap',<br/>  ...<br/>}"]
+    end
+
+    Envelope --> MetaShard
+    Envelope --> BitmapShard

Summary

ComponentPurposeLookup Time
meta_XX.jsonSHA to numeric ID mappingO(1)
shards_fwd_XX.jsonForward edges (parent to children)O(1)
shards_rev_XX.jsonReverse edges (child to parents)O(1)
LRU CacheAvoid re-loading recently used shardsO(1)

The combination of:

  1. Numeric IDs (compact representation)
  2. Roaring Bitmaps (compressed, fast set operations)
  3. Sharding by prefix (lazy loading, reduced memory)
  4. LRU caching (avoid repeated I/O)

...enables EMPTY GRAPH to traverse massive Git commit graphs with constant-time lookups.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/index.html b/docs/.vitepress/dist/index.html new file mode 100644 index 0000000..365566f --- /dev/null +++ b/docs/.vitepress/dist/index.html @@ -0,0 +1,44 @@ + + + + + + EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

EmptyGraphA graph database that lives inside Git.

Invisible storage. O(1) lookups. Zero files.

The "Wait, what?" Moment

bash
# Directory is empty
+$ ls -la
+total 0
+drwxr-xr-x  2 james  staff  64 Jan 29 12:00 .
+
+# Create a graph node (behind the scenes)
+$ node create-node.js "{"hello": "world"}"
+Created node: abc123def456...
+
+# Still no files!
+$ ls -la
+total 0
+drwxr-xr-x  2 james  staff  64 Jan 29 12:00 .
+
+# But Git knows...
+$ git log --format=%B -n 1 abc123def
+{"hello": "world"}

Why it exists

Graph databases are usually a $3B market requiring dedicated infra. EmptyGraph asks: "What if the graph database was just Git?"

It's a stunt, yes. But it's also a legitimate tool for offline-first data, audit trails, and AI agent memory that needs to be distributed, versioned, and immutable.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/internals/bitmap-index.html b/docs/.vitepress/dist/internals/bitmap-index.html new file mode 100644 index 0000000..c7eda7e --- /dev/null +++ b/docs/.vitepress/dist/internals/bitmap-index.html @@ -0,0 +1,28 @@ + + + + + + The Bitmap Index (Internals) | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

The Bitmap Index (Internals)

Warning: This is deep magic. You don't need to know this to use the library, but it helps if you want to understand the performance characteristics.

The Problem

Git stores Child -> Parent links efficiently. It stores Parent -> Child links... not at all.

The Solution

We map every 40-character SHA-1 to a 32-bit Integer ID. We then use Roaring Bitmaps to store the adjacency matrix.

Sharding

To avoid loading a 100MB index for a single query, we shard the index by SHA prefix (2 chars -> 256 shards).

  • meta_ab.json: ID mappings for SHAs starting with ab.
  • shards_fwd_ab.json: Forward edges for ab.
  • shards_rev_ab.json: Backward edges for ab.

This allows us to perform "Lazy Loading". We only load the shards relevant to the nodes you are currently visiting.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/internals/plumbing.html b/docs/.vitepress/dist/internals/plumbing.html new file mode 100644 index 0000000..afc59e8 --- /dev/null +++ b/docs/.vitepress/dist/internals/plumbing.html @@ -0,0 +1,28 @@ + + + + + + EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/stunts/event-sourcing.html b/docs/.vitepress/dist/stunts/event-sourcing.html new file mode 100644 index 0000000..0d5593e --- /dev/null +++ b/docs/.vitepress/dist/stunts/event-sourcing.html @@ -0,0 +1,45 @@ + + + + + + Event Sourcing | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Event Sourcing

The Stunt: Treating Git commits as immutable domain events, and "replaying" history to build application state.

Event Sourcing is a pattern where you don't store the "current state" (e.g., User: { name: "Alice" }). Instead, you store the sequence of events that led there:

  1. UserCreated { name: "Alice" }
  2. UserRenamed { newName: "Al" }

Git is natively an event store. It is an append-only log of immutable changes.

The Implementation

With EmptyGraph, every node is an event.

javascript
// 1. Store an event
+await graph.createNode({
+  message: JSON.stringify({ type: 'OrderPlaced', amount: 100 }),
+  parents: [previousEventSha] // Link to the chain
+});
+
+// 2. Replay to build state
+let balance = 0;
+// Note: ancestors() goes backwards in time, so we reverse it
+const history = [];
+for await (const node of graph.traversal.ancestors({ sha: 'HEAD' })) {
+  history.push(JSON.parse(node.message));
+}
+
+for (const event of history.reverse()) {
+  if (event.type === 'OrderPlaced') balance += event.amount;
+  if (event.type === 'Refunded') balance -= event.amount;
+}

Branching = Alternate Timelines

Because it's Git, you can branch your event stream.

  • Main Branch: The "official" history.
  • Feature Branch: A "What If" simulation.

You can replay a "simulation branch" to see what the state would be if you cancelled an order, without affecting the main timeline. This is incredibly powerful for financial modeling or game state prediction.

Cryptographic Proof

Every state is cryptographically verifiable. If you have the SHA of the tip of the branch, you have a mathematical guarantee that the entire history leading up to it has not been tampered with. This is built-in Blockchain tech, without the Blockchain hype.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/stunts/invisible-storage.html b/docs/.vitepress/dist/stunts/invisible-storage.html new file mode 100644 index 0000000..2815d98 --- /dev/null +++ b/docs/.vitepress/dist/stunts/invisible-storage.html @@ -0,0 +1,36 @@ + + + + + + Invisible Metadata | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Invisible Metadata

The Stunt: Storing rich application state inside your .git folder without creating a single file in your working directory.

This is the feature that usually breaks people's brains.

When you use EmptyGraph, you are interacting with Git, but you are not touching the "Index" (staging area) or the "Work Tree" (your files). You are bypassing them and writing directly to the Object Database (the .git/objects folder).

The "Empty Tree" Pattern

Every commit in Git points to a "Tree" object (a snapshot of a directory). Usually, that tree contains your source code.

But a tree can be empty. The SHA-1 of an empty tree is always constant:

4b825dc642cb6eb9a060e54bf8d69288fbee4904

We create commits that point to this tree.

  • Files: 0
  • Data: Stored in the "Commit Message"
  • History: Fully preserved

Use Case: The "Shadow" Database

Imagine you are building a CLI tool. You want to store configuration, usage history, or user preferences.

The Old Way:

  • Write to ~/.config/my-tool/config.json.
  • Now you have to manage file permissions, paths, JSON parsing corruption.

The EmptyGraph Way:

  • Initialize a hidden git repo.
  • Write updates as commits to a detached branch or a custom ref (e.g., refs/shadow/config).
javascript
// Write config
+const sha = await graph.createNode({
+  message: JSON.stringify({ theme: 'dark', retries: 3 })
+});
+await plumbing.updateRef('refs/shadow/config', sha);
+
+// Read config
+const headSha = await plumbing.readRef('refs/shadow/config');
+const config = JSON.parse(await graph.readNode(headSha));

Why?

  1. It's Clean: No pollution of the user's home directory with random config files.
  2. It's Auditable: You have a complete history of every configuration change ever made. "Why did my theme change?" -> Check the log.
  3. It's Syncable: It's just a Git ref. You can git push it to a remote for backup or sync it between machines.

The "Rootkit" Database

We call this the "Rootkit" pattern (metaphorically!) because it exists in a layer underneath what the user perceives as "the filesystem." It is persistent, versioned, and invisible.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/stunts/lagrangian-routing.html b/docs/.vitepress/dist/stunts/lagrangian-routing.html new file mode 100644 index 0000000..fe4eae5 --- /dev/null +++ b/docs/.vitepress/dist/stunts/lagrangian-routing.html @@ -0,0 +1,46 @@ + + + + + + Resource-Aware Routing | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Resource-Aware Routing

The Stunt: Routing through a graph based on "cost" (CPU, Memory, Latency) rather than just distance, using Dijkstra and A* on top of a Git repo.

Most graph traversals just look for the shortest path (fewest hops). But in distributed systems, the shortest path might be the most expensive.

EmptyGraph implements "Lagrangian Pathfinding"—a fancy term for "we check the price tag before we walk through the door."

The Scenario

Imagine you are building an AI Agent that needs to execute a sequence of tasks.

  • Node A: "Download Data" (High Bandwidth)
  • Node B: "Process Data" (High CPU)
  • Node C: "Save to S3" (Low Cost)

If Node B is overloaded, you don't want to route through it, even if it's the "shortest" path. You want the "cheapest" path.

The Code

We use weightedShortestPath with a custom weightProvider. This function is async, meaning it can fetch real-time metrics (from Prometheus, a JSON file, or another Git commit) to decide the cost of an edge.

javascript
const { path, totalCost } = await graph.traversal.weightedShortestPath({
+  from: startSha,
+  to: targetSha,
+  
+  // This is where the magic happens
+  weightProvider: async (fromSha, toSha) => {
+    // 1. Read the node data
+    const message = await graph.readNode(toSha);
+    const event = JSON.parse(message);
+    
+    // 2. Extract metrics (simulated or real)
+    const cpuLoad = event.metrics?.cpu ?? 1; // 1.0 = 100% load
+    const memory = event.metrics?.mem ?? 1;  // 1.0 = 1GB
+    
+    // 3. Calculate Lagrangian cost
+    // Cost = CPU + 1.5 * Memory
+    return cpuLoad + (memory * 1.5);
+  }
+});

Why this is cool

  1. Dynamic Topography: The shape of your graph changes based on the state of the nodes, not just their connections.
  2. Invisible Backend: You can store the metric history in the graph itself as a separate branch, and query it during traversal.
  3. A Optimization:* If you know the heuristic distance (e.g., "how many steps left?"), you can use aStarSearch to prioritize exploring promising paths first, massively pruning the search space.

Performance Note

This isn't just a toy. Because we use a MinHeap and a Roaring Bitmap Index, this traversal is extremely efficient. We only load the node data when we actually consider the edge, and we cache heavily.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/stunts/streaming.html b/docs/.vitepress/dist/stunts/streaming.html new file mode 100644 index 0000000..7e6c6a5 --- /dev/null +++ b/docs/.vitepress/dist/stunts/streaming.html @@ -0,0 +1,31 @@ + + + + + + Infinite Memory Streaming | EmptyGraph + + + + + + + + + + + + + + + + + +
Skip to content

Infinite Memory Streaming

The Stunt: Processing a graph with 10 million nodes on a Raspberry Pi without crashing Node.js.

Git history is linear, but it can be massive. If you try to git log the Linux kernel and load it all into a Javascript array, you will crash with an OutOfMemory error immediately.

EmptyGraph is designed to never hold the full graph in memory.

The Generator Pattern

We use async generators (async function*) for everything.

javascript
// This will never OOM, even if 'HEAD' has 1 billion commits.
+for await (const node of graph.iterateNodes({ ref: 'HEAD' })) {
+  process(node);
+}

How it works (Internals)

Under the hood, we spawn a git log process and pipe its stdout through a custom binary parser.

  1. Spawn: git log --format=...
  2. Stream: We receive chunks of Buffer data.
  3. Parse: We scan for NUL byte delimiters (which we use because they are illegal in git messages, making them 100% safe).
  4. Yield: As soon as we have a full record, we yield it and discard the buffer.

This means your memory usage is determined by the size of a single node, not the size of the graph.

Benchmark

We ran this on a graph with 100,000 nodes containing JSON payloads.

| Metric | Result |

StringResult
Heap Used~40 MB (Constant)
Throughput~24,000 nodes / sec
Crash?Never.

Why this matters

If you are building an audit system or an event store, you can't assume your data fits in RAM. This architecture guarantees that your system remains stable as your data grows from "Prototype" size to "Production" size.

Released under the Apache-2.0 License.

+ + + + \ No newline at end of file diff --git a/docs/.vitepress/dist/vp-icons.css b/docs/.vitepress/dist/vp-icons.css new file mode 100644 index 0000000..ddc5bd8 --- /dev/null +++ b/docs/.vitepress/dist/vp-icons.css @@ -0,0 +1 @@ +.vpi-social-github{--icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")} \ No newline at end of file diff --git a/docs/api/bitmap-index.md b/docs/api/bitmap-index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/api/empty-graph.md b/docs/api/empty-graph.md new file mode 100644 index 0000000..5bf47ef --- /dev/null +++ b/docs/api/empty-graph.md @@ -0,0 +1,19 @@ +# EmptyGraph + +The main facade class that ties everything together. + +```javascript +import EmptyGraph from '@git-stunts/empty-graph'; +const graph = new EmptyGraph({ persistence }); +``` + +## Methods + +### `createNode({ message, parents })` +Creates a new node (commit). + +### `readNode(sha)` +Reads the message of a node. + +### `rebuildIndex(ref)` +Builds the bitmap index for O(1) lookups. diff --git a/docs/api/graph-service.md b/docs/api/graph-service.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/api/index.md b/docs/api/index.md new file mode 100644 index 0000000..19ad3d6 --- /dev/null +++ b/docs/api/index.md @@ -0,0 +1,10 @@ +# API Reference + +The primary entry point is the `EmptyGraph` class. + +## Core Classes + +- [EmptyGraph](./empty-graph) - The main facade. +- [GraphService](./graph-service) - CRUD operations for nodes. +- [TraversalService](./traversal-service) - Algorithms (BFS, DFS, A*). +- [BitmapIndex](./bitmap-index) - The O(1) indexing engine. diff --git a/docs/api/traversal-service.md b/docs/api/traversal-service.md new file mode 100644 index 0000000..a374c71 --- /dev/null +++ b/docs/api/traversal-service.md @@ -0,0 +1,14 @@ +# TraversalService + +The engine for walking the graph. + +## Methods + +### `bfs({ start, maxDepth })` +Breadth-First Search generator. + +### `shortestPath({ from, to })` +Finds shortest path using Bidirectional BFS. + +### `weightedShortestPath({ from, to, weightProvider })` +Dijkstra's algorithm with custom weights (e.g., for Lagrangian routing). diff --git a/docs/guide/architecture.md b/docs/guide/architecture.md new file mode 100644 index 0000000..59b6fe8 --- /dev/null +++ b/docs/guide/architecture.md @@ -0,0 +1,36 @@ +# Architecture + +EmptyGraph follows a strict **Hexagonal Architecture** (Ports & Adapters). + +## The Hexagon + +```mermaid +flowchart TD + User --> EG[EmptyGraph Facade] + EG --> GS[GraphService] + EG --> TS[TraversalService] + + GS --> Ports + TS --> Ports + + subgraph Ports + GPP[GraphPersistencePort] + ISP[IndexStoragePort] + end + + subgraph Adapters + Ports --> GGA[GitGraphAdapter] + end + + GGA --> Git[Git Plumbing] +``` + +## Components + +- **Domain Layer:** Pure logic. `GraphService` manages nodes, `TraversalService` manages walking the graph. +- **Ports Layer:** Interfaces that define *how* we talk to the outside world. +- **Adapters Layer:** The implementation. `GitGraphAdapter` translates our domain calls into `git` CLI commands. + +## Why this matters + +This decoupling means the "Brain" (Traversal) doesn't know it's running on Git. It just asks for "neighbors." This allowed us to swap in the Bitmap Index without changing the traversal algorithms. diff --git a/docs/guide/comparison.md b/docs/guide/comparison.md new file mode 100644 index 0000000..6521b03 --- /dev/null +++ b/docs/guide/comparison.md @@ -0,0 +1,32 @@ +# Database Comparison + +EmptyGraph is a specialized storage engine. It is not a general-purpose replacement for relational or document databases. Understanding where it fits in the landscape is key to successful implementation. + +## Comparison Table + +| Feature | EmptyGraph | PostgreSQL | Neo4j | SQLite | +| :--- | :--- | :--- | :--- | :--- | +| **Persistence** | Git Object DB | Disk (Row/Col) | Graph Native | Single File | +| **Query Lang** | JS Traversal | SQL | Cypher | SQL | +| **Concurrency** | Lock-file (Optimistic) | MVCC / Locking | ACID | File-locking | +| **History** | Built-in (Git) | Manual (Audit logs) | Manual | Manual | +| **Offline Sync** | Native (Git Push/Pull) | Complex (Logical Rep) | Complex | No (Single file) | +| **Indexing** | Roaring Bitmaps | B-Tree / GIN | B-Tree / Hash | B-Tree | +| **Integrity** | Merkle DAG | Constraints / FKs | Schema-less/Optional | Constraints | + +## Why EmptyGraph? + +### 1. The Distributed Nature +If your data needs to be shared across a fleet of edge devices or developer machines, Git is the world's most battle-tested synchronization engine. EmptyGraph allows you to treat your database as a repository that you can `fork`, `branch`, and `merge`. + +### 2. Built-in Audit Trail +In a standard database, the history of "who changed what" is a feature you have to build. In EmptyGraph, it is the primary primitive. Every state change is a cryptographically signed commit. + +### 3. Environment Native +EmptyGraph is "Ghost Software." It requires no server, no background process, and no external files. It hides inside the `.git` folder that already exists in your project. + +## When NOT to use EmptyGraph + +- **High-Frequency Writes:** Every write is a `git commit-tree`. If you need thousands of writes per second, use a dedicated WAL-based database like Postgres. +- **Complex Ad-hoc Queries:** If you need to perform arbitrary joins across millions of nodes without knowing the traversal path ahead of time, a SQL engine or Cypher will outperform raw JS traversal. +- **Large Binary Blobs:** Git is not a File Hosting service. Storing large images or videos in commit messages will lead to massive repository bloat. EmptyGraph is for **Metadata** and **Event Logs**. diff --git a/docs/guide/core-concepts.md b/docs/guide/core-concepts.md new file mode 100644 index 0000000..9c9c847 --- /dev/null +++ b/docs/guide/core-concepts.md @@ -0,0 +1,30 @@ +# Core Concepts + +To understand EmptyGraph, you need to understand three things: Nodes, Edges, and the Index. + +## 1. The Node (A Ghost Commit) + +A **Node** is just a Git Commit. +- **ID:** The SHA-1 hash of the commit. +- **Data:** The commit message (String/JSON). +- **Metadata:** Author, Committer, Date. + +Crucially, the commit points to the **Empty Tree**. This means it has no file content. It is a "Ghost" commit. + +## 2. The Edge (Parent Pointers) + +An **Edge** is the relationship between commits. +- Git natively supports **Backward Edges** (Child points to Parent). +- This creates a **Directed Acyclic Graph (DAG)**. + +## 3. The Index (The Cheat Code) + +Git does not support **Forward Edges** (Parent points to Children). To find children, you have to scan the whole repo. + +EmptyGraph solves this with a **Roaring Bitmap Index**. +- We assign every SHA an integer ID. +- We store adjacency lists in compressed bitmaps. +- We save this index *back into Git* as a set of sharded JSON files. + +When you ask `graph.getChildren(parentSha)`, we check the index (O(1)). +When you ask `graph.getParents(childSha)`, we check the index (O(1)). diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md new file mode 100644 index 0000000..a987b56 --- /dev/null +++ b/docs/guide/getting-started.md @@ -0,0 +1,73 @@ +# Getting Started + +Ready to perform some stunts? + +## Installation + +```bash +npm install @git-stunts/empty-graph @git-stunts/plumbing +``` + +## The 30-Second Setup + +You need two things: +1. **Plumbing:** To talk to Git. +2. **Adapter:** To translate Git to Graph. + +```javascript +import GitPlumbing from '@git-stunts/plumbing'; +import EmptyGraph, { GitGraphAdapter } from '@git-stunts/empty-graph'; + +// 1. Point to a directory (it will be `git init`'d automatically if needed) +const plumbing = new GitPlumbing({ cwd: './my-ghost-db' }); + +// 2. Create the adapter +const persistence = new GitGraphAdapter({ plumbing }); + +// 3. Initialize the Graph +const graph = new EmptyGraph({ persistence }); + +// 4. Create your first Invisible Node +const sha = await graph.createNode({ + message: JSON.stringify({ + type: 'Genesis', + payload: 'Hello from the other side' + }) +}); + +console.log(`Created node: ${sha}`); +``` + +## Reading it back + +You can read by SHA, or iterate through history. + +```javascript +// Direct Read (O(1)) +const data = await graph.readNode(sha); + +// Stream History +for await (const node of graph.iterateNodes({ ref: sha })) { + console.log(node.message); +} +``` + +## Enabling the "Supercharger" (Bitmap Index) + +By default, we just use Git. But if you want to find **children** (traverse forward) instantly, you need the index. + +```javascript +// Build the index (scans history and saves a binary tree to git) +const indexOid = await graph.rebuildIndex(sha); + +// Load it for O(1) powers +await graph.loadIndex(indexOid); + +// Now you can look into the future +const children = await graph.getChildren(sha); +``` + +## Next Steps + +- Check out [Event Sourcing](/stunts/event-sourcing) to see how to build a time-traveling application. +- Look at [Resource-Aware Routing](/stunts/lagrangian-routing) for AI agent use cases. diff --git a/docs/guide/interactive-demo.md b/docs/guide/interactive-demo.md new file mode 100644 index 0000000..73bfdd6 --- /dev/null +++ b/docs/guide/interactive-demo.md @@ -0,0 +1,43 @@ +# Interactive Demo + +EmptyGraph includes a comprehensive interactive demo that runs in Docker. It demonstrates a real-world e-commerce event store. + +## Quick Start + +```bash +# 1. Setup the demo environment +npm run demo:setup + +# 2. Run the interactive explorer +npm run demo:explore + +# 3. Inspect the bitmap index distribution +npm run demo:inspect +``` + +## What the Demo Shows + +### 1. Event Replay +The explorer walks backwards through the event history, demonstrating `graph.traversal.ancestors()`. + +### 2. State Projection +Replays events through a reducer to rebuild current application state (Users, Carts, Orders). + +### 3. Branching & Timelines +Demonstrates how Git branches represent alternate timelines (e.g., a "Cancelled Order" scenario). + +### 4. Advanced Traversal +- **Shortest Path:** Bidirectional BFS finding the shortest route between events. +- **Topological Sort:** Kahn's algorithm ensuring events are processed in dependency order. + +## Manual Exploration + +You can drop into the demo container to run raw Git commands against the "Invisible" database: + +```bash +npm run demo +# Now inside the container +git log --oneline --graph --all +``` + +See the [WALKTHROUGH.md](https://github.com/git-stunts/empty-graph/blob/main/examples/WALKTHROUGH.md) for a detailed step-by-step guide. diff --git a/docs/guide/operations.md b/docs/guide/operations.md new file mode 100644 index 0000000..c18148a --- /dev/null +++ b/docs/guide/operations.md @@ -0,0 +1,72 @@ +# Operations & Safety + +Running EmptyGraph in production requires understanding how Git manages the lifecycle of objects. + +## 1. Garbage Collection (The Reaper) + +Git is designed to clean up "unreachable" objects. + +When you call `graph.createNode()`, you create a **Commit Object** in the database. However, if no **Reference** (Branch, Tag, or Custom Ref) points to that commit (or one of its descendants), Git considers it "dangling." + +Standard `git gc` (Garbage Collection) will delete these dangling commits eventually (usually after 2 weeks). + +### The Rule of Anchors +**You must anchor your graph tip to a Ref.** + +```javascript +// 1. Create the node +const sha = await graph.createNode({ ... }); + +// 2. Anchor it immediately! +// This tells Git: "This object is important, do not delete it." +await plumbing.updateRef('refs/heads/main', sha); +``` + +As long as the "Tip" of your graph is pointed to by a ref, the entire history behind it is safe. + +## 2. Concurrency & Locking + +Git uses file-based locking (`index.lock`, `HEAD.lock`) to ensure atomic updates. + +### The Race Condition +If two processes try to write to the repository at the exact same millisecond, one will succeed, and the other will fail with: +`fatal: Unable to create '.../index.lock': File exists.` + +### Handling Locks +1. **Retry Logic:** Your application layer should catch this specific error and retry after a short delay (e.g., 50ms). +2. **Stale Locks:** If a process crashes hard *during* a write, the `.lock` file might be left behind, freezing the repo. + * **Solution:** On application startup, check for stale lock files (older than X minutes) and remove them. Use caution! + +## 3. Handling Forks (Conflicts) + +In a Content-Addressable Store, "Merge Conflicts" look different than in text files. + +If User A and User B both append a new node to the same Parent: +1. User A creates Node `A` (Parent: `P`) +2. User B creates Node `B` (Parent: `P`) + +Git accepts both. You now have a **Fork** in your graph. + +### Resolving Forks +To bring the history back together, you must create a **Merge Node**. + +```javascript +// A node with TWO parents +const mergeSha = await graph.createNode({ + message: JSON.stringify({ type: 'Merge', strategy: 'union' }), + parents: [shaA, shaB] +}); +``` + +Your application traversal logic (`ancestors()`) naturally handles this. It will visit both branches. It is up to your **Application Logic** to decide how to combine the state (e.g., "Last Write Wins" or "Union of Events"). + +## 4. Backups + +Because your database is a Git repository, your backup strategy is standard: + +```bash +# Push to a remote (GitHub, GitLab, S3, Bare Repo) +git push origin main +``` + +You can also treat the `.git` folder as a standard artifact for snapshots. diff --git a/docs/guide/roadmap.md b/docs/guide/roadmap.md new file mode 100644 index 0000000..bb503d6 --- /dev/null +++ b/docs/guide/roadmap.md @@ -0,0 +1,34 @@ +# Roadmap & Future Directions + +EmptyGraph is an evolving experiment. Here is what is on the horizon. + +## Phase 1: Performance & Scalability (In Progress) + +### Incremental Indexing (SPEC-0001) +Currently, `rebuildIndex` scans the entire history. For repositories with 10M+ nodes, this is inefficient. We are moving to a model where we only scan the "Delta" since the last index build and merge it into the existing binary shards. + +### Binary Shards (CBOR) +Replacing JSON shards with CBOR (Concise Binary Object Representation) to reduce index size on disk by ~40% and improve load times via zero-copy deserialization. + +## Phase 2: Query Capabilities + +### Pipes & Filters (SPEC-0003) +A streaming query API that allows developers to chain operations: +```javascript +graph.query() + .from('HEAD') + .filter(node => node.type === 'OrderPlaced') + .map(node => node.amount) + .reduce((sum, val) => sum + val, 0); +``` + +### Logical Transaction Batching (ADR-005) +Ensuring that a sequence of `createNode` calls are treated as a single "Logical Transaction" that succeeds or fails as a unit, utilizing Git's atomic reference updates. + +## Phase 3: Developer Experience + +### VitePress Documentation +A complete overhaul of the documentation to provide a first-class learning experience (You are here!). + +### Browser Support +Exploring a WASM-based Git plumbing layer to allow EmptyGraph to run directly in the browser using the Origin Private File System (OPFS). diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md new file mode 100644 index 0000000..8f24cd0 --- /dev/null +++ b/docs/guide/troubleshooting.md @@ -0,0 +1,52 @@ +# Troubleshooting + +Common issues and how to resolve them. + +## 1. "fatal: Unable to create '.../index.lock': File exists" + +**Symptoms:** Node creation or index building fails with a locking error. + +**Cause:** Git uses lock files to ensure atomicity. If a process crashes while writing, the lock file remains. + +**Solution:** +Locate and delete the lock file in your `.git` directory: +```bash +rm .git/index.lock +# or if it was a ref update +rm .git/refs/heads/main.lock +``` + +## 2. Low Performance during Traversal + +**Symptoms:** `getChildren()` or `getParents()` is taking seconds instead of milliseconds. + +**Cause:** +1. **Missing Index:** You are likely not using the Bitmap Index and are falling back to raw Git scans. +2. **Native Bindings:** You are using the Javascript fallback for Roaring Bitmaps instead of the native C++ bindings. + +**Solution:** +1. Ensure you have built and loaded the index: `await graph.loadIndex(oid)`. +2. Install the native bindings: + ```bash + npm install roaring + ``` + EmptyGraph will automatically detect and use the native version if available. + +## 3. Data Missing after `git gc` + +**Symptoms:** Previously created nodes are no longer retrievable. + +**Cause:** You created nodes but did not anchor them to a Git Reference. Git's Garbage Collector deleted them as "unreachable." + +**Solution:** Always call `plumbing.updateRef()` after creating a node to ensure it is part of a reachable history. See the [Operations Guide](./operations) for details. + +## 4. "Invalid Ref Format" Errors + +**Symptoms:** `listNodes` or `iterateNodes` throws a validation error. + +**Cause:** EmptyGraph enforces strict security patterns on Git refs to prevent command injection. + +**Solution:** +- Avoid starting ref names with `-` or `--`. +- Use only alphanumeric characters, `.`, `/`, `-`, `_`, `^`, `~`. +- Ensure the ref length is under 1024 characters. diff --git a/docs/guide/what-is-this.md b/docs/guide/what-is-this.md new file mode 100644 index 0000000..87315c6 --- /dev/null +++ b/docs/guide/what-is-this.md @@ -0,0 +1,42 @@ +# What is EmptyGraph? + +EmptyGraph is a TypeScript library that provides a graph database interface over Git's internal object storage. + +It allows developers to create, traverse, and query a Directed Acyclic Graph (DAG) where every node is a Git commit. By utilizing the **Empty Tree Pattern**, it stores data exclusively within the `.git` directory, keeping the user's working directory clean. + +## The Architecture + +Git is fundamentally a content-addressable filesystem. EmptyGraph treats it as a database backend, providing three key layers of abstraction: + +### 1. The Storage Layer (Git Objects) +Standard Git commits are used as the storage unit. +* **Immutability:** Once written, a node cannot be changed, only referenced. +* **Verification:** Every node ID (SHA-1) is a cryptographic hash of its content and ancestry. +* **Distribution:** Data can be replicated using standard `git push` and `git pull` commands. + +### 2. The Indexing Layer (Roaring Bitmaps) +Git is optimized for historical traversal (`Child -> Parent`). It is inefficient at forward traversal (`Parent -> Child`). + +EmptyGraph solves this by maintaining a secondary index: +* **Mapping:** 40-char SHA-1 hashes are mapped to 32-bit integers. +* **Bitmaps:** Adjacency lists are stored as compressed Roaring Bitmaps. +* **Persistence:** This index is sharded and stored back into Git as a set of JSON blobs, allowing for O(1) lookups in both directions. + +### 3. The Application Layer (GraphService) +A high-level API for interacting with the graph. +* `createNode`: Transactional write to the Git ODB. +* `traversal`: Algorithms including BFS, DFS, Dijkstra, and A*. +* `streaming`: Async generators for memory-efficient processing of large graphs. + +## Why use Git as a Database? + +While not a replacement for high-throughput transactional databases (like PostgreSQL), this architecture offers unique advantages for specific domains: + +### Offline-First & Distributed +Applications inherit Git's distributed nature. Data can be written offline, branched, and merged later. This is ideal for edge computing, local-first software, and distributed configuration management. + +### Auditable History +Because the database *is* a Git repository, the audit trail is built-in. Every change is timestamped, signed, and inextricably linked to its predecessor. + +### Zero-Installation +For tools that already exist within a Git repository (CLI tools, CI/CD pipelines, dev-tools), EmptyGraph provides a structured database without requiring a separate server process (like Docker or SQLite). It simply uses the `.git` folder that is already there. \ No newline at end of file diff --git a/docs/images/empty-graph-social.jpg b/docs/images/empty-graph-social.jpg new file mode 100644 index 0000000..c635634 Binary files /dev/null and b/docs/images/empty-graph-social.jpg differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..2a4b45b --- /dev/null +++ b/docs/index.md @@ -0,0 +1,61 @@ +--- +layout: home + +hero: + name: EmptyGraph + text: Graph Database on Git Object Storage + tagline: Invisible storage. O(1) lookups. Zero files. + actions: + - theme: brand + text: Implementation Guide + link: /guide/what-is-this + - theme: alt + text: View on GitHub + link: https://github.com/git-stunts/empty-graph + +features: + - title: 📦 Content-Addressable + details: Leverages Git's internal Merkle DAG to store immutable, cryptographically verifiable data nodes. + - title: ⚡ Indexed Traversal + details: Implements a secondary Roaring Bitmap index to enable O(1) bidirectional lookups (Parent ↔ Child), bypassing Git's scan limitations. + - title: 👻 The Empty Tree Pattern + details: Commits point to the Git "Empty Tree" object. Data is stored strictly in commit messages, leaving the working directory untouched. + - title: 🌊 Streaming Architecture + details: Designed for massive datasets. Uses async generators to process millions of nodes with constant memory overhead. +--- + +## Technical Overview + +EmptyGraph is a storage engine that implements a graph database on top of Git's plumbing. It abstracts `git commit-tree`, `git log`, and `git cat-file` into a structured Node API. + +### The Storage Mechanism + +Unlike standard Git usage, EmptyGraph does not track files. It utilizes the **Empty Tree** (`4b825dc642cb6eb9a060e54bf8d69288fbee4904`) as the root of every commit. + +1. **Nodes** are Git Commits. Data is serialized into the commit message. +2. **Edges** are Git Parent Pointers. +3. **State** is the Git Object Database (`.git/objects`). + +```bash +# 1. The Working Directory remains empty +$ ls -la +total 0 +drwxr-xr-x 2 user staff 64 Jan 29 12:00 . + +# 2. Data is written directly to the Object DB +$ node create-node.js "{"type": "UserCreated", "id": 1}" +Created node: abc123def456... + +# 3. Data is retrievable via Git plumbing +$ git log --format=%B -n 1 abc123def +{"type": "UserCreated", "id": 1} +``` + +## Primary Use Cases + +* **Audit Trails:** Leveraging Git's immutability and cryptographic signing for secure logs. +* **Invisible Configuration:** Storing application state in a repo without polluting the file system. +* **Event Sourcing:** Using the commit graph as an append-only event log with built-in branching and merging. +* **AI Agent Memory:** utilizing the graph structure for resource-aware routing and decision trees. + +``` \ No newline at end of file diff --git a/docs/internals/bitmap-index.md b/docs/internals/bitmap-index.md new file mode 100644 index 0000000..c051269 --- /dev/null +++ b/docs/internals/bitmap-index.md @@ -0,0 +1,19 @@ +# The Bitmap Index (Internals) + +> **Warning:** This is deep magic. You don't need to know this to use the library, but it helps if you want to understand the performance characteristics. + +## The Problem +Git stores `Child -> Parent` links efficiently. It stores `Parent -> Child` links... not at all. + +## The Solution +We map every 40-character SHA-1 to a 32-bit Integer ID. +We then use **Roaring Bitmaps** to store the adjacency matrix. + +### Sharding +To avoid loading a 100MB index for a single query, we shard the index by SHA prefix (2 chars -> 256 shards). + +- `meta_ab.json`: ID mappings for SHAs starting with `ab`. +- `shards_fwd_ab.json`: Forward edges for `ab`. +- `shards_rev_ab.json`: Backward edges for `ab`. + +This allows us to perform "Lazy Loading". We only load the shards relevant to the nodes you are currently visiting. diff --git a/docs/internals/plumbing.md b/docs/internals/plumbing.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/stunts/event-sourcing.md b/docs/stunts/event-sourcing.md new file mode 100644 index 0000000..63cb0c8 --- /dev/null +++ b/docs/stunts/event-sourcing.md @@ -0,0 +1,47 @@ +# Event Sourcing + +> **The Stunt:** Treating Git commits as immutable domain events, and "replaying" history to build application state. + +Event Sourcing is a pattern where you don't store the "current state" (e.g., `User: { name: "Alice" }`). Instead, you store the sequence of events that led there: +1. `UserCreated { name: "Alice" }` +2. `UserRenamed { newName: "Al" }` + +Git is natively an event store. It is an append-only log of immutable changes. + +## The Implementation + +With EmptyGraph, every node is an event. + +```javascript +// 1. Store an event +await graph.createNode({ + message: JSON.stringify({ type: 'OrderPlaced', amount: 100 }), + parents: [previousEventSha] // Link to the chain +}); + +// 2. Replay to build state +let balance = 0; +// Note: ancestors() goes backwards in time, so we reverse it +const history = []; +for await (const node of graph.traversal.ancestors({ sha: 'HEAD' })) { + history.push(JSON.parse(node.message)); +} + +for (const event of history.reverse()) { + if (event.type === 'OrderPlaced') balance += event.amount; + if (event.type === 'Refunded') balance -= event.amount; +} +``` + +## Branching = Alternate Timelines + +Because it's Git, you can branch your event stream. + +- **Main Branch:** The "official" history. +- **Feature Branch:** A "What If" simulation. + +You can replay a "simulation branch" to see what the state *would* be if you cancelled an order, without affecting the main timeline. This is incredibly powerful for financial modeling or game state prediction. + +## Cryptographic Proof + +Every state is cryptographically verifiable. If you have the SHA of the tip of the branch, you have a mathematical guarantee that the entire history leading up to it has not been tampered with. This is built-in Blockchain tech, without the Blockchain hype. diff --git a/docs/stunts/invisible-storage.md b/docs/stunts/invisible-storage.md new file mode 100644 index 0000000..72c6d3f --- /dev/null +++ b/docs/stunts/invisible-storage.md @@ -0,0 +1,58 @@ +# Invisible Metadata + +> **The Stunt:** Storing rich application state inside your `.git` folder without creating a single file in your working directory. + +This is the feature that usually breaks people's brains. + +When you use **EmptyGraph**, you are interacting with Git, but you are not touching the "Index" (staging area) or the "Work Tree" (your files). You are bypassing them and writing directly to the **Object Database** (the `.git/objects` folder). + +## The "Empty Tree" Pattern + +Every commit in Git points to a "Tree" object (a snapshot of a directory). Usually, that tree contains your source code. + +But a tree can be empty. +The SHA-1 of an empty tree is always constant: + +``` +4b825dc642cb6eb9a060e54bf8d69288fbee4904 +``` + +We create commits that point to *this* tree. + +- **Files:** 0 +- **Data:** Stored in the "Commit Message" +- **History:** Fully preserved + +## Use Case: The "Shadow" Database + +Imagine you are building a CLI tool. You want to store configuration, usage history, or user preferences. + +**The Old Way:** +- Write to `~/.config/my-tool/config.json`. +- Now you have to manage file permissions, paths, JSON parsing corruption. + +**The EmptyGraph Way:** +- Initialize a hidden git repo. +- Write updates as commits to a detached branch or a custom ref (e.g., `refs/shadow/config`). + +```javascript +// Write config +const sha = await graph.createNode({ + message: JSON.stringify({ theme: 'dark', retries: 3 }) +}); +await plumbing.updateRef('refs/shadow/config', sha); + +// Read config +const headSha = await plumbing.readRef('refs/shadow/config'); +const config = JSON.parse(await graph.readNode(headSha)); +``` + +## Why? + +1. **It's Clean:** No pollution of the user's home directory with random config files. +2. **It's Auditable:** You have a complete history of every configuration change ever made. "Why did my theme change?" -> Check the log. +3. **It's Syncable:** It's just a Git ref. You can `git push` it to a remote for backup or sync it between machines. + +## The "Rootkit" Database + +We call this the "Rootkit" pattern (metaphorically!) because it exists in a layer *underneath* what the user perceives as "the filesystem." It is persistent, versioned, and invisible. diff --git a/docs/stunts/lagrangian-routing.md b/docs/stunts/lagrangian-routing.md new file mode 100644 index 0000000..003cb4b --- /dev/null +++ b/docs/stunts/lagrangian-routing.md @@ -0,0 +1,52 @@ +# Resource-Aware Routing + +> **The Stunt:** Routing through a graph based on "cost" (CPU, Memory, Latency) rather than just distance, using Dijkstra and A* on top of a Git repo. + +Most graph traversals just look for the *shortest* path (fewest hops). But in distributed systems, the shortest path might be the most expensive. + +**EmptyGraph** implements "Lagrangian Pathfinding"—a fancy term for "we check the price tag before we walk through the door." + +## The Scenario + +Imagine you are building an AI Agent that needs to execute a sequence of tasks. +- **Node A:** "Download Data" (High Bandwidth) +- **Node B:** "Process Data" (High CPU) +- **Node C:** "Save to S3" (Low Cost) + +If Node B is overloaded, you don't want to route through it, even if it's the "shortest" path. You want the "cheapest" path. + +## The Code + +We use `weightedShortestPath` with a custom `weightProvider`. This function is async, meaning it can fetch real-time metrics (from Prometheus, a JSON file, or another Git commit) to decide the cost of an edge. + +```javascript +const { path, totalCost } = await graph.traversal.weightedShortestPath({ + from: startSha, + to: targetSha, + + // This is where the magic happens + weightProvider: async (fromSha, toSha) => { + // 1. Read the node data + const message = await graph.readNode(toSha); + const event = JSON.parse(message); + + // 2. Extract metrics (simulated or real) + const cpuLoad = event.metrics?.cpu ?? 1; // 1.0 = 100% load + const memory = event.metrics?.mem ?? 1; // 1.0 = 1GB + + // 3. Calculate Lagrangian cost + // Cost = CPU + 1.5 * Memory + return cpuLoad + (memory * 1.5); + } +}); +``` + +## Why this is cool + +1. **Dynamic Topography:** The shape of your graph changes based on the *state* of the nodes, not just their connections. +2. **Invisible Backend:** You can store the metric history *in the graph itself* as a separate branch, and query it during traversal. +3. **A* Optimization:** If you know the heuristic distance (e.g., "how many steps left?"), you can use `aStarSearch` to prioritize exploring promising paths first, massively pruning the search space. + +## Performance Note + +This isn't just a toy. Because we use a **MinHeap** and a **Roaring Bitmap Index**, this traversal is extremely efficient. We only load the node data when we actually consider the edge, and we cache heavily. diff --git a/docs/stunts/streaming.md b/docs/stunts/streaming.md new file mode 100644 index 0000000..864d10a --- /dev/null +++ b/docs/stunts/streaming.md @@ -0,0 +1,44 @@ +# Infinite Memory Streaming + +> **The Stunt:** Processing a graph with 10 million nodes on a Raspberry Pi without crashing Node.js. + +Git history is linear, but it can be massive. If you try to `git log` the Linux kernel and load it all into a Javascript array, you will crash with an `OutOfMemory` error immediately. + +**EmptyGraph** is designed to never hold the full graph in memory. + +## The Generator Pattern + +We use async generators (`async function*`) for everything. + +```javascript +// This will never OOM, even if 'HEAD' has 1 billion commits. +for await (const node of graph.iterateNodes({ ref: 'HEAD' })) { + process(node); +} +``` + +## How it works (Internals) + +Under the hood, we spawn a `git log` process and pipe its stdout through a custom binary parser. + +1. **Spawn:** `git log --format=...` +2. **Stream:** We receive chunks of `Buffer` data. +3. **Parse:** We scan for `NUL` byte delimiters (which we use because they are illegal in git messages, making them 100% safe). +4. **Yield:** As soon as we have a full record, we yield it and discard the buffer. + +This means your memory usage is determined by the size of a *single node*, not the size of the graph. + +## Benchmark + +We ran this on a graph with **100,000 nodes** containing JSON payloads. + +| Metric | Result | +|String|Result| +| --- | --- | +| **Heap Used** | ~40 MB (Constant) | +| **Throughput** | ~24,000 nodes / sec | +| **Crash?** | Never. | + +## Why this matters + +If you are building an audit system or an event store, you can't assume your data fits in RAM. This architecture guarantees that your system remains stable as your data grows from "Prototype" size to "Production" size. diff --git a/package-lock.json b/package-lock.json index 72f3715..c4d4fa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@git-stunts/empty-graph", - "version": "1.0.0", + "version": "2.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@git-stunts/empty-graph", - "version": "1.0.0", + "version": "2.5.0", "license": "Apache-2.0", "dependencies": { "@git-stunts/plumbing": "^2.8.0", @@ -19,12 +19,373 @@ "@git-stunts/docker-guard": "^0.1.0", "eslint": "^9.17.0", "prettier": "^3.4.2", - "vitest": "^2.1.8" + "vitepress": "^1.6.4", + "vitest": "^2.1.8", + "vue": "^3.5.27" }, "engines": { "node": ">=20.0.0" } }, + "node_modules/@algolia/abtesting": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.13.0.tgz", + "integrity": "sha512-Zrqam12iorp3FjiKMXSTpedGYznZ3hTEOAr2oCxI8tbF8bS1kQHClyDYNq/eV0ewMNLyFkgZVWjaS+8spsOYiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.47.0.tgz", + "integrity": "sha512-aOpsdlgS9xTEvz47+nXmw8m0NtUiQbvGWNuSEb7fA46iPL5FxOmOUZkh8PREBJpZ0/H8fclSc7BMJCVr+Dn72w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.47.0.tgz", + "integrity": "sha512-EcF4w7IvIk1sowrO7Pdy4Ako7x/S8+nuCgdk6En+u5jsaNQM4rTT09zjBPA+WQphXkA2mLrsMwge96rf6i7Mow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.47.0.tgz", + "integrity": "sha512-Wzg5Me2FqgRDj0lFuPWFK05UOWccSMsIBL2YqmTmaOzxVlLZ+oUqvKbsUSOE5ud8Fo1JU7JyiLmEXBtgDKzTwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.47.0.tgz", + "integrity": "sha512-Ci+cn/FDIsDxSKMRBEiyKrqybblbk8xugo6ujDN1GSTv9RIZxwxqZYuHfdLnLEwLlX7GB8pqVyqrUSlRnR+sJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.47.0.tgz", + "integrity": "sha512-gsLnHPZmWcX0T3IigkDL2imCNtsQ7dR5xfnwiFsb+uTHCuYQt+IwSNjsd8tok6HLGLzZrliSaXtB5mfGBtYZvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.47.0.tgz", + "integrity": "sha512-PDOw0s8WSlR2fWFjPQldEpmm/gAoUgLigvC3k/jCSi/DzigdGX6RdC0Gh1RR1P8Cbk5KOWYDuL3TNzdYwkfDyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.47.0.tgz", + "integrity": "sha512-b5hlU69CuhnS2Rqgsz7uSW0t4VqrLMLTPbUpEl0QVz56rsSwr1Sugyogrjb493sWDA+XU1FU5m9eB8uH7MoI0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.47.0.tgz", + "integrity": "sha512-WvwwXp5+LqIGISK3zHRApLT1xkuEk320/EGeD7uYy+K8WwDd5OjXnhjuXRhYr1685KnkvWkq1rQ/ihCJjOfHpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.47.0.tgz", + "integrity": "sha512-j2EUFKAlzM0TE4GRfkDE3IDfkVeJdcbBANWzK16Tb3RHz87WuDfQ9oeEW6XiRE1/bEkq2xf4MvZesvSeQrZRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.47.0.tgz", + "integrity": "sha512-+kTSE4aQ1ARj2feXyN+DMq0CIDHJwZw1kpxIunedkmpWUg8k3TzFwWsMCzJVkF2nu1UcFbl7xsIURz3Q3XwOXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.47.0.tgz", + "integrity": "sha512-Ja+zPoeSA2SDowPwCNRbm5Q2mzDvVV8oqxCQ4m6SNmbKmPlCfe30zPfrt9ho3kBHnsg37pGucwOedRIOIklCHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.47.0.tgz", + "integrity": "sha512-N6nOvLbaR4Ge+oVm7T4W/ea1PqcSbsHR4O58FJ31XtZjFPtOyxmnhgCmGCzP9hsJI6+x0yxJjkW5BMK/XI8OvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.47.0.tgz", + "integrity": "sha512-z1oyLq5/UVkohVXNDEY70mJbT/sv/t6HYtCvCwNrOri6pxBJDomP9R83KOlwcat+xqBQEdJHjbrPh36f1avmZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -654,6 +1015,23 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.68", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.68.tgz", + "integrity": "sha512-bQPl1zuZlX6AnofreA1v7J+hoPncrFMppqGboe/SH54jZO37meiBUGBqNOxEpc0HKfZGxJaVVJwZd4gdMYu3hw==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, "node_modules/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -1097,6 +1475,93 @@ "win32" ] }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1104,6 +1569,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1111,6 +1586,76 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, "node_modules/@vitest/expect": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", @@ -1224,6 +1769,271 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vue/compiler-core": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz", + "integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.27", + "entities": "^7.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz", + "integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", + "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.27", + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz", + "integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.27.tgz", + "integrity": "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.27.tgz", + "integrity": "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.27.tgz", + "integrity": "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.27", + "@vue/runtime-core": "3.5.27", + "@vue/shared": "3.5.27", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.27.tgz", + "integrity": "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27" + }, + "peerDependencies": { + "vue": "3.5.27" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz", + "integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/abbrev": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", @@ -1282,6 +2092,32 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/algoliasearch": { + "version": "5.47.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.47.0.tgz", + "integrity": "sha512-AGtz2U7zOV4DlsuYV84tLp2tBbA7RPtLA44jbVH4TTpDcc1dIWmULjHSsunlhscbzDydnjuFlNhflR3nV4VJaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.13.0", + "@algolia/client-abtesting": "5.47.0", + "@algolia/client-analytics": "5.47.0", + "@algolia/client-common": "5.47.0", + "@algolia/client-insights": "5.47.0", + "@algolia/client-personalization": "5.47.0", + "@algolia/client-query-suggestions": "5.47.0", + "@algolia/client-search": "5.47.0", + "@algolia/ingestion": "1.47.0", + "@algolia/monitoring": "1.47.0", + "@algolia/recommend": "5.47.0", + "@algolia/requester-browser-xhr": "5.47.0", + "@algolia/requester-fetch": "5.47.0", + "@algolia/requester-node-http": "5.47.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1322,6 +2158,16 @@ "dev": true, "license": "MIT" }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1376,6 +2222,17 @@ "node": ">=6" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -1410,6 +2267,28 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-error": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", @@ -1449,6 +2328,17 @@ "dev": true, "license": "MIT" }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1465,6 +2355,22 @@ "node": "^14.18.0 || >=16.10.0" } }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1480,6 +2386,13 @@ "node": ">= 8" } }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1514,6 +2427,16 @@ "dev": true, "license": "MIT" }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -1523,6 +2446,27 @@ "node": ">=8" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, "node_modules/encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", @@ -1533,6 +2477,19 @@ "iconv-lite": "^0.6.2" } }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -1880,6 +2837,16 @@ "dev": true, "license": "ISC" }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, "node_modules/fs-minipass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", @@ -1981,8 +2948,64 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, "node_modules/http-cache-semantics": { @@ -2102,6 +3125,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2240,6 +3276,129 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2392,6 +3551,13 @@ "license": "ISC", "optional": true }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, "node_modules/minizlib": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", @@ -2404,6 +3570,13 @@ "node": ">= 18" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2558,6 +3731,18 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2688,6 +3873,13 @@ "node": ">= 14.16" } }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2737,6 +3929,17 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/preact": { + "version": "10.28.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.2.tgz", + "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2787,6 +3990,17 @@ "node": ">=10" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2797,6 +4011,33 @@ "node": ">=6" } }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2817,6 +4058,13 @@ "node": ">= 4" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/roaring": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/roaring/-/roaring-2.7.0.tgz", @@ -2893,6 +4141,14 @@ "license": "MIT", "optional": true }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -2928,6 +4184,23 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -2986,6 +4259,27 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ssri": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", @@ -3013,6 +4307,21 @@ "dev": true, "license": "MIT" }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3026,6 +4335,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3039,6 +4361,13 @@ "node": ">=8" } }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, "node_modules/tar": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", @@ -3122,6 +4451,17 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3161,6 +4501,79 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3171,6 +4584,36 @@ "punycode": "^2.1.0" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", @@ -3254,6 +4697,48 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, "node_modules/vitest": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", @@ -3320,6 +4805,28 @@ } } }, + "node_modules/vue": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", + "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-sfc": "3.5.27", + "@vue/runtime-dom": "3.5.27", + "@vue/server-renderer": "3.5.27", + "@vue/shared": "3.5.27" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3409,6 +4916,17 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index caec2bd..50bd1b5 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,12 @@ "types": "./index.d.ts", "typesVersions": { "*": { - "service": ["./index.d.ts"], - "node": ["./index.d.ts"] + "service": [ + "./index.d.ts" + ], + "node": [ + "./index.d.ts" + ] } }, "exports": { @@ -35,6 +39,9 @@ "format": "prettier --write .", "test:local": "vitest run test/unit", "benchmark:local": "vitest bench test/benchmark", + "docs:dev": "vitepress dev docs", + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs", "demo": "cd examples && docker compose up -d && docker compose exec demo bash", "demo:setup": "cd examples && docker compose up -d && docker compose exec demo sh -c 'cd /app && npm install --silent && cd /demo && node /app/examples/setup.js'", "demo:explore": "cd examples && docker compose exec demo node /app/examples/explore.js", @@ -55,10 +62,12 @@ }, "devDependencies": { "@eslint/js": "^9.17.0", + "@git-stunts/docker-guard": "^0.1.0", "eslint": "^9.17.0", "prettier": "^3.4.2", + "vitepress": "^1.6.4", "vitest": "^2.1.8", - "@git-stunts/docker-guard": "^0.1.0" + "vue": "^3.5.27" }, "files": [ "src",