diff --git a/.vitepress/config.mjs b/.vitepress/config.mjs index 34f8e72..869b033 100644 --- a/.vitepress/config.mjs +++ b/.vitepress/config.mjs @@ -29,27 +29,44 @@ export default defineConfig({ lastUpdated: true, nav: [ { text: "Home", link: "/" }, - { text: "Why Idempotency", link: "/why-idempotency" }, + { text: "Learn", link: "/learn/" }, { text: "Specs", link: "/specs" } ], - sidebar: [ - { - text: "Documentation", - items: [ - { text: "Why Idempotency", link: "/why-idempotency" }, - { text: "Specifications", link: "/specs" } - ] - }, - { - text: "Projects", - items: [ - { - text: "idempot-js", - link: "https://github.com/idempot-dev/idempot-js" - } - ] - } - ], + sidebar: { + "/learn/": [ + { + text: "Learn", + items: [ + { text: "Overview", link: "/learn/" }, + { text: "Why Idempotency", link: "/learn/why" }, + { + text: "Duplicated vs Repeated", + link: "/learn/duplicated-vs-repeated" + }, + { + text: "Client Key Strategies", + link: "/learn/client-key-strategies" + }, + { text: "Spec Compliance", link: "/learn/spec" } + ] + } + ], + "/": [ + { + text: "Documentation", + items: [{ text: "Specifications", link: "/specs" }] + }, + { + text: "Projects", + items: [ + { + text: "idempot-js", + link: "https://github.com/idempot-dev/idempot-js" + } + ] + } + ] + }, socialLinks: [{ icon: "github", link: "https://github.com/idempot-dev" }] } }); diff --git a/.vitepress/theme/index.js b/.vitepress/theme/index.js new file mode 100644 index 0000000..122808b --- /dev/null +++ b/.vitepress/theme/index.js @@ -0,0 +1,30 @@ +import { h, nextTick, watch } from "vue"; +import DefaultTheme from "vitepress/theme"; +import { useData } from "vitepress"; +import { createMermaidRenderer } from "vitepress-mermaid-renderer"; + +export default { + extends: DefaultTheme, + Layout: () => { + const { isDark } = useData(); + + const initMermaid = () => { + const _mermaidRenderer = createMermaidRenderer({ + theme: isDark.value ? "dark" : "forest" + }); + }; + + // initial mermaid setup + nextTick(() => initMermaid()); + + // on theme change, re-render mermaid charts + watch( + () => isDark.value, + () => { + initMermaid(); + } + ); + + return h(DefaultTheme.Layout); + } +}; diff --git a/docs/learn/client-key-strategies.md b/docs/learn/client-key-strategies.md new file mode 100644 index 0000000..c374091 --- /dev/null +++ b/docs/learn/client-key-strategies.md @@ -0,0 +1,77 @@ +# Client Key Strategies + +The client generates idempotency keys. Both strategies create a transfer record first: + +## Strategy 1: Random Keys + +Create a transfer record, generate a random UUID, store it on the record: + +```javascript +// Create transfer record first +const transfer = await db.transfers.create({ + supplier_id: supplierId, + invoice_id: invoiceId, + iban, + amount: 10000, + currency: "EUR", + description: "Monthly consulting fee", + internal_reason: `invoice-${supplierId}-${invoiceId}`, + idempotency_key: crypto.randomUUID(), + status: "pending" +}); + +await fetch("/api/transfers", { + method: "POST", + headers: { + "Content-Type": "application/json", + "Idempotency-Key": transfer.idempotency_key + }, + body: JSON.stringify({ + iban: transfer.iban, + amount: transfer.amount, + currency: transfer.currency, + description: transfer.description, + internal_reason: transfer.internal_reason + }) +}); +``` + +**Benefit**: No coupling between your database IDs and external API contracts — you can change your ID scheme without affecting idempotency. + +## Strategy 2: Database ID as Key + +Use the transfer's database-generated ID directly: + +```javascript +// Create transfer record first +const transfer = await db.transfers.create({ + supplier_id: supplierId, + invoice_id: invoiceId, + iban, + amount: 10000, + currency: "EUR", + description: "Monthly consulting fee", + internal_reason: `invoice-${supplierId}-${invoiceId}`, + status: "pending" +}); + +// Use transfer ID directly +const idempotencyKey = transfer.id; + +await fetch("/api/transfers", { + method: "POST", + headers: { + "Content-Type": "application/json", + "Idempotency-Key": idempotencyKey + }, + body: JSON.stringify({ + iban: transfer.iban, + amount: transfer.amount, + currency: transfer.currency, + description: transfer.description, + internal_reason: transfer.internal_reason + }) +}); +``` + +**Benefit**: Single source of truth — the transfer ID is your idempotency key. diff --git a/docs/learn/duplicated-vs-repeated.md b/docs/learn/duplicated-vs-repeated.md new file mode 100644 index 0000000..4fe0d17 --- /dev/null +++ b/docs/learn/duplicated-vs-repeated.md @@ -0,0 +1,135 @@ +# Duplicated vs Repeated Operations + +Idempotency protects against **duplicated** operations from network retries while allowing **repeated** operations—new requests with the same business parameters. + +## The Difference + +| Duplicated | Repeated | +| ------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| Same request sent multiple times due to network failures, timeouts, or client retries | New operation that happens to have the same parameters | +| Should return the same response | Should create a new result | +| Protected by idempotency | Allowed by idempotency | + +## Example: Monthly Invoice Payments + +Your company pays the same vendor each month: + +- **January**: Transfer €100 to DE89370400440532013000 for invoice INV-001 +- **February**: Transfer €100 to DE89370400440532013000 for invoice INV-002 + +Same IBAN, same amount, same currency—but two distinct operations. + +### Request Model + +```javascript +// POST /api/transfers +{ + "iban": "DE89370400440532013000", + "amount": 10000, // cents + "currency": "EUR", + "description": "Monthly consulting fee", + "internal_reason": "invoice-550e8400-e29b-41d4-a716-446655440000" +} +``` + +The `internal_reason` field uniquely identifies this payment in your system. + +## How Idempotency Works + +### Duplicated Request (Retry) + +```http +POST /api/transfers +Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 +Content-Type: application/json + +{ + "iban": "DE89370400440532013000", + "amount": 10000, + "currency": "EUR", + "description": "Monthly consulting fee", + "internal_reason": "invoice-550e8400-e29b-41d4-a716-446655440000" +} +``` + +Network timeout occurs. Client retries: + +```http +POST /api/transfers +Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000 +Content-Type: application/json + +{ + "iban": "DE89370400440532013000", + "amount": 10000, + "currency": "EUR", + "description": "Monthly consulting fee", + "internal_reason": "invoice-550e8400-e29b-41d4-a716-446655440000" +} +``` + +**Same key, same body** → server returns cached response. No double payment. + +### Repeated Operation (New Invoice) + +```http +POST /api/transfers +Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890 +Content-Type: application/json + +{ + "iban": "DE89370400440532013000", + "amount": 10000, + "currency": "EUR", + "description": "Monthly consulting fee", + "internal_reason": "invoice-a1b2c3d4-e5f6-7890-abcd-ef1234567890" +} +``` + +**Different key, different body** (different `internal_reason`) → server processes as new transfer. + +**Choosing a key strategy?** See [Client Key Strategies](/learn/client-key-strategies) for patterns on generating and managing idempotency keys. + +## Server Implementation + +**Note:** The following example uses [idempot-js](https://js.idempot.dev) middleware with the Hono framework. For framework-specific implementations, see the [idempot-js documentation](https://js.idempot.dev). + +```javascript +import { Hono } from "hono"; +import { idempotency } from "idempot-js/hono"; +import { RedisIdempotencyStore } from "idempot-js/stores/redis"; + +const app = new Hono(); +const store = new RedisIdempotencyStore({ client: redis }); + +app.post("/api/transfers", idempotency({ store }), async (c) => { + const { iban, amount, currency, description, internal_reason } = + await c.req.json(); + + // Process transfer - only executed once per unique idempotency key + const transferId = await processTransfer({ + iban, + amount, + currency, + internal_reason + }); + + return c.json( + { + transferId, + status: "completed", + internal_reason + }, + 201 + ); +}); +``` + +## Summary + +| Scenario | Idempotency Key | Request Body | Fingerprint | Result | +| --------------------- | --------------- | --------------------------- | ----------- | --------------- | +| Retry of same request | Same | Same | Same | Cached response | +| New invoice payment | Different | Different `internal_reason` | Different | New operation | + +The combination of **new key per operation** and **unique `internal_reason` in each request body** ensures retries return cached responses while new operations process normally. diff --git a/docs/learn/index.md b/docs/learn/index.md new file mode 100644 index 0000000..6168846 --- /dev/null +++ b/docs/learn/index.md @@ -0,0 +1,28 @@ +# Learn + +Idempotency is essential for reliable distributed systems. When networks fail and clients retry requests, idempotency prevents duplicate transactions—no double charges, no duplicate orders. + +## Key Concepts + +### Why Idempotency Matters + +Every API that processes payments, creates orders, or modifies state needs idempotency. Without it, network failures and client retries create duplicate transactions. **[Learn why →](/learn/why)** + +### Duplicated vs Repeated Operations + +Idempotency protects against duplicates from retries while allowing legitimate repeated operations. Use a different idempotency key for each distinct business operation. **[Learn the difference →](/learn/duplicated-vs-repeated)** + +### Client Key Strategies + +How should you generate idempotency keys? Learn patterns for managing keys in your client applications. **[See strategies →](/learn/client-key-strategies)** + +### IETF Specification + +This library implements the IETF draft standard for idempotency keys. Understanding the spec helps you implement idempotency correctly and interoperate with other systems. **[Read the spec compliance guide →](/learn/spec)** + +## What You'll Learn + +- The problem duplicates create in distributed systems +- How the idempotency-key pattern works +- What the IETF specification requires +- Implementation details for each requirement diff --git a/docs/learn/spec.md b/docs/learn/spec.md new file mode 100644 index 0000000..100fe99 --- /dev/null +++ b/docs/learn/spec.md @@ -0,0 +1,60 @@ +# IETF Spec Compliance + +The [idempot-js](https://js.idempot.dev) library implements [draft-ietf-httpapi-idempotency-key-header-07](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-07), the IETF standard for the Idempotency-Key HTTP header. + +This document details how the library complies with each requirement in the specification. + +## Implemented Requirements + +**Note:** This page describes [idempot-js](https://js.idempot.dev) implementation of the IETF specification. + +### MUST Requirements (Required) + +| Requirement | Section | Implementation | +| ------------------------------------ | ------- | ------------------------------------------------------------------------- | +| Idempotency-Key as String | 2.1 | ✅ Header value extracted as string | +| Unique idempotency keys | 2.2 | ✅ Key stored with request fingerprint to ensure uniqueness | +| Identify idempotency key from header | 2.5.2 | ✅ Parses `Idempotency-Key` header (configurable via `headerName` option) | +| Generate idempotency fingerprint | 2.5.2 | ✅ SHA-256 hash of method + path + body | +| Enforce idempotency | 2.6 | ✅ Returns cached response for duplicate requests | + +### SHOULD Requirements (Recommended) + +| Requirement | Section | Implementation | +| ----------------------------------------------- | ------- | ------------------------------------------------------------------------------ | +| Use UUID or random identifier | 2.2 | ✅ Library doesn't generate keys (client responsibility), but validates format | +| Publish expiration policy | 2.3 | ✅ Configurable via `ttlMs` option | +| Return 400 if key missing | 2.7 | ✅ Optional via `required: true` option | +| Return 422 if key reused with different payload | 2.7 | ✅ Returns 422 with problem details when fingerprint mismatch detected | +| Return 409 for concurrent requests | 2.7 | ✅ Returns 409 Conflict when original request still processing | + +### MAY Requirements (Optional) + +| Requirement | Section | Implementation | +| ----------------------- | ------- | --------------------------------------------------------------------------------- | +| Idempotency fingerprint | 2.4 | ✅ SHA-256 hash of method + path + body (configurable via `hashAlgorithm` option) | +| Time-based expiry | 2.3 | ✅ Configurable via `ttlMs` option, defaults to 24 hours | + +## Error Responses + +The library follows the spec's error handling recommendations: + +| Scenario | Status Code | Response | +| --------------------------------------- | ----------- | ----------------------------------------------------------- | +| Missing Idempotency-Key (when required) | 400 | Problem Details JSON with link to documentation | +| Key reused with different payload | 422 | Problem Details JSON with "Idempotency-Key is already used" | +| Concurrent request (still processing) | 409 | Problem Details JSON with "request is outstanding" | + +## What's Not Covered + +The spec leaves some things to the application layer: + +- **Key format**: The spec recommends UUIDs, but the library accepts any string value. +- **Store implementation**: The spec doesn't mandate storage implementation. We provide Redis, PostgreSQL, MySQL, SQLite, and Bun SQL stores. +- **Key generation**: The spec says clients should generate keys. We don't generate keys—clients provide them. + +## Compliance Status + +✅ **Full compliance** with draft-ietf-httpapi-idempotency-key-header-07 + +All MUST and SHOULD requirements are implemented. The library gives you the flexibility to choose which optional features to enable based on your API's needs. diff --git a/docs/learn/why.md b/docs/learn/why.md new file mode 100644 index 0000000..45a9809 --- /dev/null +++ b/docs/learn/why.md @@ -0,0 +1,71 @@ +# Why Idempotency Matters + +In distributed systems, networks timeout, load balancers retry, users double-click. Without idempotency, these failures create duplicate transactions: double charges, duplicate orders, inconsistent state. + +## The Problem + +Duplicate requests happen more often than you'd think: + +| Cause | Example | +| ---------------- | ------------------------------------- | +| User behavior | Double-clicking a submit button | +| Client retries | Automatic retry on connection timeout | +| Network issues | Request succeeds but response is lost | +| Load balancers | Backend timeout triggers retry | +| Webhook delivery | Provider retries failed deliveries | + +```mermaid +sequenceDiagram + participant Client + participant Server + + Client->>Server: POST /api/transfers + Server-->>Client: 201 Created (response LOST) + Note over Client: Network timeout
Client retries... + Client->>Server: POST /api/transfers + Server-->>Client: 201 Created + Note over Server: ❌ Duplicate created +``` + +Each duplicate request creates side effects: duplicate payments, duplicate orders, corrupted data. + +## The Pattern + +Major APIs like Stripe and PayPal use a simple pattern to solve this: + +1. **Client generates a unique key** — typically a UUID for each unique operation +2. **Key sent as header** — `Idempotency-Key: ` +3. **Server stores key + response** — in your database or cache +4. **On duplicate request** — server returns cached response instead of reprocessing + +```mermaid +sequenceDiagram + participant Client + participant Server + + Client->>Server: POST /api/transfers
Idempotency-Key: abc-123 + Note over Server: Store key, process request + Server-->>Client: 201 Created + Note over Client: Network timeout
Client retries... + Client->>Server: POST /api/transfers
Idempotency-Key: abc-123 + Note over Server: Key found
Return cached response + Server-->>Client: 201 Created + Note over Server: ✅ No duplicate +``` + +This makes any request safely retryable. The server either processes it once and caches the result, or recognizes the key and returns the previous result. + +## Benefits + +- **Fault tolerance**: Network interruptions don't cause duplicate transactions +- **Simplified retry logic**: Clients can safely retry without complex deduplication +- **Better UX**: Users don't wonder "did that go through?" +- **API reliability**: Stripe, PayPal, and major processors all use this pattern + +[idempot-js](https://js.idempot.dev) implements the [IETF Idempotency-Key Header draft specification](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-07) for Node.js, Bun, and Deno applications. + +## Further Learning + + + +**[Try, try again](https://www.youtube.com/watch?v=29NNiZhXe2Q)** — Sam Newman explains the importance of idempotency in distributed systems at LeadDev Berlin 2025. diff --git a/docs/superpowers/plans/2026-04-03-learn-section-import.md b/docs/superpowers/plans/2026-04-03-learn-section-import.md new file mode 100644 index 0000000..7e68822 --- /dev/null +++ b/docs/superpowers/plans/2026-04-03-learn-section-import.md @@ -0,0 +1,605 @@ +# Learn Section Import Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Import the /learn/ section from idempot-js VitePress site, replacing the existing "Why Idempotency" page. + +**Architecture:** Add mermaid plugin support to VitePress, copy 5 learn pages from idempot-js with context modifications for framework-specific code, convert sidebar from array to object format for path-specific sidebars, update navigation to replace "Why Idempotency" with "Learn". + +**Tech Stack:** VitePress 2.0, vitepress-plugin-mermaid 2.0.17, Markdown, Mermaid diagrams + +--- + +## Task 1: Add Mermaid Plugin Dependency + +**Files:** + +- Modify: `package.json` + +- [ ] **Step 1: Add vitepress-mermaid-renderer dependency** + +Open `package.json` and add the mermaid plugin to devDependencies after vitepress: + +```json +"devDependencies": { + "@commitlint/cli": "^20.5.0", + "@commitlint/config-conventional": "^20.5.0", + "@eslint/js": "^10.0.1", + "eslint": "^10.1.0", + "eslint-config-prettier": "^10.1.8", + "globals": "^17.4.0", + "husky": "^9.1.7", + "lint-staged": "^16.4.0", + "prettier": "^3.8.1", + "vitepress": "^2.0.0-alpha.17", + "vitepress-mermaid-renderer": "^1.1.20" +} +``` + +Note: Using vitepress-mermaid-renderer instead of vitepress-plugin-mermaid for VitePress 2.x compatibility. + +- [ ] **Step 2: Install dependencies** + +Run: `npm install` + +Expected: Dependencies install successfully, package-lock.json updates. + +- [ ] **Step 3: Verify installation** + +Run: `grep vitepress-mermaid-renderer package-lock.json` + +Expected: Shows vitepress-mermaid-renderer entry with version 1.1.20. + +- [ ] **Step 4: Commit** + +```bash +git add package.json package-lock.json +git commit -m "chore: add vitepress-plugin-mermaid dependency" +``` + +--- + +## Task 2: Configure Mermaid in VitePress + +**Files:** + +- Create: `.vitepress/theme/index.js` + +- [ ] **Step 1: Create theme directory** + +Run: `mkdir -p .vitepress/theme` + +- [ ] **Step 2: Create theme/index.js** + +Create `.vitepress/theme/index.js` with the following content: + +```javascript +import { h, nextTick, watch } from "vue"; +import DefaultTheme from "vitepress/theme"; +import { useData } from "vitepress"; +import { createMermaidRenderer } from "vitepress-mermaid-renderer"; + +export default { + extends: DefaultTheme, + Layout: () => { + const { isDark } = useData(); + + const initMermaid = () => { + const mermaidRenderer = createMermaidRenderer({ + theme: isDark.value ? "dark" : "forest" + }); + }; + + // initial mermaid setup + nextTick(() => initMermaid()); + + // on theme change, re-render mermaid charts + watch( + () => isDark.value, + () => { + initMermaid(); + } + ); + + return h(DefaultTheme.Layout); + } +}; +``` + +- [ ] **Step 3: Verify configuration loads** + +Run: `npm run dev` + +Expected: Development server starts without errors. + +- [ ] **Step 4: Stop dev server** + +Press: `Ctrl+C` + +- [ ] **Step 5: Commit** + +```bash +git add .vitepress/theme/index.js +git commit -m "feat: configure mermaid renderer in vitepress theme" +``` + +Note: Using vitepress-mermaid-renderer with theme-based configuration (compatible with VitePress 2.x) instead of vitepress-plugin-mermaid (requires VitePress 1.x). + +--- + +## Task 3: Create Learn Directory and Index Page + +**Files:** + +- Create: `docs/learn/index.md` + +- [ ] **Step 1: Create learn directory** + +Run: `mkdir -p docs/learn` + +- [ ] **Step 2: Create index.md** + +Read source: `~/code/idempot-dev/idempot-js/docs/learn/index.md` + +Create `docs/learn/index.md` with identical content (no modifications needed for index): + +```markdown +# Learn + +Idempotency is essential for reliable distributed systems. When networks fail and clients retry requests, idempotency prevents duplicate transactions—no double charges, no duplicate orders. + +## Key Concepts + +### Why Idempotency Matters + +Every API that processes payments, creates orders, or modifies state needs idempotency. Without it, network failures and client retries create duplicate transactions. **[Learn why →](/learn/why)** + +### Duplicated vs Repeated Operations + +Idempotency protects against duplicates from retries while allowing legitimate repeated operations. Use a different idempotency key for each distinct business operation. **[Learn the difference →](/learn/duplicated-vs-repeated)** + +### Client Key Strategies + +How should you generate idempotency keys? Learn patterns for managing keys in your client applications. **[See strategies →](/learn/client-key-strategies)** + +### IETF Specification + +This library implements the IETF draft standard for idempotency keys. Understanding the spec helps you implement idempotency correctly and interoperate with other systems. **[Read the spec compliance guide →](/learn/spec)** + +## What You'll Learn + +- The problem duplicates create in distributed systems +- How the idempotency-key pattern works +- What the IETF specification requires +- Implementation details for each requirement +``` + +- [ ] **Step 3: Verify file created** + +Run: `ls -la docs/learn/` + +Expected: Shows `index.md` file. + +- [ ] **Step 4: Commit** + +```bash +git add docs/learn/index.md +git commit -m "docs: add learn section index page" +``` + +--- + +## Task 4: Create Why Idempotency Page with Diagrams + +**Files:** + +- Create: `docs/learn/why.md` + +- [ ] **Step 1: Copy source file** + +Run: `cp ~/code/idempot-dev/idempot-js/docs/learn/why.md docs/learn/why.md` + +Expected: File copied successfully. + +- [ ] **Step 2: Verify file exists** + +Run: `ls -la docs/learn/why.md` + +Expected: Shows file details, file exists. + +- [ ] **Step 3: Verify content preserved** + +Run: `grep -c "mermaid" docs/learn/why.md` + +Expected: Returns 2 (two mermaid diagrams present). + +Run: `grep -c "youtube" docs/learn/why.md` + +Expected: Returns 1 (YouTube embed present). + +- [ ] **Step 4: Commit** + +```bash +git add docs/learn/why.md +git commit -m "docs: add why idempotency page with mermaid diagrams" +``` + +--- + +## Task 5: Create Duplicated vs Repeated Page with Context + +**Files:** + +- Create: `docs/learn/duplicated-vs-repeated.md` + +- [ ] **Step 1: Copy source file** + +Run: `cp ~/code/idempot-dev/idempot-js/docs/learn/duplicated-vs-repeated.md docs/learn/duplicated-vs-repeated.md` + +Expected: File copied successfully. + +- [ ] **Step 2: Add context note before Hono example** + +Use the edit tool to insert the context note after the "## Server Implementation" heading. + +The file currently has: + +````markdown +## Server Implementation + +```javascript +import { Hono } from "hono"; +``` +```` + +Change it to: + +````markdown +## Server Implementation + +**Note:** The following example uses idempot-js middleware with the Hono framework. For framework-specific implementations, see the [idempot-js documentation](https://github.com/idempot-dev/idempot-js). + +```javascript +import { Hono } from "hono"; +``` +```` + +- [ ] **Step 3: Verify edit** + +Run: `grep -A 2 "## Server Implementation" docs/learn/duplicated-vs-repeated.md` + +Expected: Shows the heading followed by the context note. + +- [ ] **Step 4: Commit** + +```bash +git add docs/learn/duplicated-vs-repeated.md +git commit -m "docs: add duplicated vs repeated page with framework context" +``` + +--- + +## Task 6: Create Client Key Strategies Page + +**Files:** + +- Create: `docs/learn/client-key-strategies.md` + +- [ ] **Step 1: Copy source file** + +Run: `cp ~/code/idempot-dev/idempot-js/docs/learn/client-key-strategies.md docs/learn/client-key-strategies.md` + +Expected: File copied successfully. + +- [ ] **Step 2: Verify file exists** + +Run: `ls -la docs/learn/client-key-strategies.md` + +Expected: Shows file details, file exists. + +- [ ] **Step 3: Verify content** + +Run: `grep "Strategy" docs/learn/client-key-strategies.md | head -n 2` + +Expected: Shows "Strategy 1: Random Keys" and "Strategy 2: Database ID as Key". + +- [ ] **Step 4: Commit** + +```bash +git add docs/learn/client-key-strategies.md +git commit -m "docs: add client key strategies page" +``` + +--- + +## Task 7: Create Spec Compliance Page + +**Files:** + +- Create: `docs/learn/spec.md` + +- [ ] **Step 1: Copy source file** + +Run: `cp ~/code/idempot-dev/idempot-js/docs/learn/spec.md docs/learn/spec.md` + +Expected: File copied successfully. + +- [ ] **Step 2: Add context note at start of requirements section** + +Use the edit tool to insert the context note after the "## Implemented Requirements" heading. + +The file currently has: + +```markdown +## Implemented Requirements + +### MUST Requirements (Required) +``` + +Change it to: + +```markdown +## Implemented Requirements + +**Note:** This page describes idempot-js implementation of the IETF specification. For other implementations, refer to your framework's documentation. + +### MUST Requirements (Required) +``` + +- [ ] **Step 3: Verify edit** + +Run: `grep -A 3 "## Implemented Requirements" docs/learn/spec.md` + +Expected: Shows the heading followed by the context note. + +- [ ] **Step 4: Commit** + +```bash +git add docs/learn/spec.md +git commit -m "docs: add IETF spec compliance page with implementation context" +``` + +--- + +## Task 8: Update Navigation and Sidebar + +**Files:** + +- Modify: `.vitepress/config.mjs` + +- [ ] **Step 1: Update navigation** + +Replace the nav section to change "Why Idempotency" to "Learn": + +```javascript +nav: [ + { text: "Home", link: "/" }, + { text: "Learn", link: "/learn/" }, + { text: "Specs", link: "/specs" } +]; +``` + +- [ ] **Step 2: Convert sidebar to object format** + +Replace the entire sidebar array with object format for path-specific sidebars: + +```javascript +sidebar: { + "/learn/": [ + { + text: "Learn", + items: [ + { text: "Overview", link: "/learn/" }, + { text: "Why Idempotency", link: "/learn/why" }, + { text: "Duplicated vs Repeated", link: "/learn/duplicated-vs-repeated" }, + { text: "Client Key Strategies", link: "/learn/client-key-strategies" }, + { text: "Spec Compliance", link: "/learn/spec" } + ] + } + ], + "/": [ + { + text: "Documentation", + items: [ + { text: "Specifications", link: "/specs" } + ] + }, + { + text: "Projects", + items: [ + { + text: "idempot-js", + link: "https://github.com/idempot-dev/idempot-js" + } + ] + } + ] +} +``` + +Note: "Why Idempotency" is removed from Documentation section since it's now under Learn. + +- [ ] **Step 3: Verify configuration** + +Run: `npm run dev` + +Navigate to `http://localhost:5173/learn/` + +Expected: Learn index page loads with correct sidebar. + +- [ ] **Step 4: Stop dev server** + +Press: `Ctrl+C` + +- [ ] **Step 5: Commit** + +```bash +git add .vitepress/config.mjs +git commit -m "feat: update navigation to add learn section, remove why-idempotency" +``` + +--- + +## Task 9: Delete Old Why Idempotency Page + +**Files:** + +- Delete: `docs/why-idempotency.md` + +- [ ] **Step 1: Delete file** + +Run: `rm docs/why-idempotency.md` + +- [ ] **Step 2: Verify deletion** + +Run: `git status` + +Expected: Shows `deleted: docs/why-idempotency.md` + +- [ ] **Step 3: Commit** + +```bash +git add docs/why-idempotency.md +git commit -m "docs: remove old why-idempotency page (replaced by learn section)" +``` + +--- + +## Task 10: Run Tests and Verify + +**Files:** + +- None (testing only) + +- [ ] **Step 1: Start development server** + +Run: `npm run dev` + +- [ ] **Step 2: Test learn index page** + +Navigate to: `http://localhost:5173/learn/` + +Expected: Learn index page loads with sidebar showing all 5 pages. + +- [ ] **Step 3: Test mermaid diagrams** + +Navigate to: `http://localhost:5173/learn/why` + +Expected: Two sequence diagrams render correctly after "The Problem" and "The Pattern" sections. + +- [ ] **Step 4: Test YouTube embed** + +On `/learn/why`, scroll to bottom. + +Expected: YouTube video embed appears and can be played. + +- [ ] **Step 5: Test sidebar navigation** + +Click each sidebar link: + +- Overview → /learn/ +- Why Idempotency → /learn/why +- Duplicated vs Repeated → /learn/duplicated-vs-repeated +- Client Key Strategies → /learn/client-key-strategies +- Spec Compliance → /learn/spec + +Expected: Each page loads correctly. + +- [ ] **Step 6: Test internal links** + +On `/learn/`, click "Learn why →" + +Expected: Navigates to `/learn/why` + +- [ ] **Step 7: Test code examples with syntax highlighting** + +Navigate to: `http://localhost:5173/learn/duplicated-vs-repeated` + +Expected: JavaScript/Hono code examples display with syntax highlighting. + +- [ ] **Step 8: Test top navigation** + +Click "Learn" in top nav. + +Expected: Navigates to `/learn/` + +- [ ] **Step 9: Stop dev server** + +Press: `Ctrl+C` + +- [ ] **Step 10: Build for production** + +Run: `npm run build` + +Expected: Build completes successfully without errors. + +- [ ] **Step 11: Preview production build** + +Run: `npm run preview` + +Navigate to: `http://localhost:4173/learn/` + +Expected: Production build works correctly with all pages accessible. + +- [ ] **Step 12: Stop preview** + +Press: `Ctrl+C` + +--- + +## Task 11: Final Verification + +- [ ] **Step 1: Check git status** + +Run: `git status` + +Expected: Working tree clean (all changes committed). + +- [ ] **Step 2: Review commit history** + +Run: `git log --oneline -n 10` + +Expected: See all 9 commits in order: + +1. chore: add vitepress-plugin-mermaid dependency +2. feat: configure mermaid diagram support in vitepress +3. docs: add learn section index page +4. docs: add why idempotency page with mermaid diagrams +5. docs: add duplicated vs repeated page with framework context +6. docs: add client key strategies page +7. docs: add IETF spec compliance page with implementation context +8. feat: update navigation to add learn section, remove why-idempotency +9. docs: remove old why-idempotency page (replaced by learn section) + +- [ ] **Step 3: Verify file structure** + +Run: `find docs/learn -type f` + +Expected: + +``` +docs/learn/client-key-strategies.md +docs/learn/duplicated-vs-repeated.md +docs/learn/index.md +docs/learn/spec.md +docs/learn/why.md +``` + +- [ ] **Step 4: Confirm old file deleted** + +Run: `ls docs/why-idempotency.md` + +Expected: `No such file or directory` + +--- + +## Success Criteria + +✓ All 5 learn pages accessible at /learn/\* paths +✓ Mermaid diagrams render correctly +✓ YouTube video embeds properly +✓ Navigation works for both desktop and mobile +✓ Internal links between learn pages work correctly +✓ Code examples display with syntax highlighting +✓ Production build succeeds +✓ All 9 commits in logical order with descriptive messages diff --git a/docs/superpowers/specs/2026-04-03-learn-section-import-design.md b/docs/superpowers/specs/2026-04-03-learn-section-import-design.md new file mode 100644 index 0000000..d8c458d --- /dev/null +++ b/docs/superpowers/specs/2026-04-03-learn-section-import-design.md @@ -0,0 +1,219 @@ +# Learn Section Import Design + +## Overview + +Import the `/learn/` section from the idempot-js VitePress site into idempot.dev, replacing the existing "Why Idempotency" page. + +## Goals + +- Replace the simple "Why Idempotency" page with a comprehensive learn section +- Preserve all content including mermaid diagrams and YouTube embed +- Maintain site coherence while acknowledging framework-specific examples + +## Scope + +**Import:** 5 pages from idempot-js/docs/learn/: + +- index.md (overview) +- why.md (with mermaid diagrams, YouTube video) +- duplicated-vs-repeated.md (with code examples) +- client-key-strategies.md (JavaScript patterns) +- spec.md (IETF compliance) + +**Replace:** Current docs/why-idempotency.md + +## Architecture + +### File Structure + +``` +docs/ + ├── learn/ + │ ├── index.md + │ ├── why.md + │ ├── duplicated-vs-repeated.md + │ ├── client-key-strategies.md + │ └── spec.md + ├── index.md (existing) + └── specs/ (existing) + +Delete: docs/why-idempotency.md +``` + +### Navigation + +**Top nav:** Simple link to /learn/ (not a dropdown) + +```javascript +{ text: "Learn", link: "/learn/" } +``` + +**Sidebar:** Context-aware sidebar (object format, not array) + +Current sidebar is array format. Must convert to object format for path-specific sidebars: + +```javascript +sidebar: { + "/learn/": [ + { + text: "Learn", + items: [ + { text: "Overview", link: "/learn/" }, + { text: "Why Idempotency", link: "/learn/why" }, + { text: "Duplicated vs Repeated", link: "/learn/duplicated-vs-repeated" }, + { text: "Client Key Strategies", link: "/learn/client-key-strategies" }, + { text: "Spec Compliance", link: "/learn/spec" } + ] + } + ], + "/": [ + { + text: "Documentation", + items: [ + { text: "Why Idempotency", link: "/why-idempotency" }, + { text: "Specifications", link: "/specs" } + ] + }, + { + text: "Projects", + items: [ + { text: "idempot-js", link: "https://github.com/idempot-dev/idempot-js" } + ] + } + ] +} +``` + +**Important:** The "/" path sidebar will be replaced in commit 3 when we update navigation. + +## Technical Changes + +### Dependencies + +Add to package.json: + +```json +"vitepress-plugin-mermaid": "^2.0.17" +``` + +**Note:** Version matches idempot-js to ensure consistent diagram rendering. + +### VitePress Configuration + +```javascript +import { defineConfig } from "vitepress"; +import { withMermaid } from "vitepress-plugin-mermaid"; + +export default withMermaid( + defineConfig({ + srcDir: "docs", + markdown: { mermaid: true }, + vite: { + optimizeDeps: { + include: [ + "dayjs", + "@braintree/sanitize-url", + "debug", + "cytoscape", + "cytoscape-cose-bilkent" + ] + } + }, + themeConfig: { + nav: [ + { text: "Home", link: "/" }, + { text: "Learn", link: "/learn/" }, + { text: "Specs", link: "/specs" } + ], + sidebar: { + "/learn/": [ + /* learn sidebar items */ + ] + // existing sidebars... + } + } + }) +); +``` + +## Content Adaptations + +### Framework Examples + +Keep framework-specific code (Hono, Redis, etc.) but add context: + +**Example note to add:** + +```markdown +**Note:** This example uses idempot-js middleware with the Hono framework. +See [idempot-js documentation](https://github.com/idempot-dev/idempot-js) +for framework-specific implementations. +``` + +### Content Placement + +Add notes in these files: + +- `duplicated-vs-repeated.md` - Before Hono code example +- `client-key-strategies.md` - At start of strategy examples +- `spec.md` - At start of implementation section + +### YouTube Video + +Keep the video embed in `why.md` as-is (relevant general content about idempotency). + +### Mermaid Diagrams + +Preserve sequence diagrams in `why.md` without modification. + +## Implementation Plan + +**Commit 1: Add mermaid infrastructure** + +- Add vitepress-plugin-mermaid to package.json +- Update .vitepress/config.mjs with mermaid plugin +- Add vite optimizeDeps configuration + +**Commit 2: Copy and adapt learn pages** + +- Create docs/learn/ directory +- Copy 5 markdown files from idempot-js +- Add context notes to framework-specific sections + +**Commit 3: Update navigation** + +- Replace "Why Idempotency" with "Learn" in nav +- Convertsidebar from array to object format +- Add "/learn/" sidebar configuration +- Update "/" sidebar: replace "Why Idempotency" with link to "/learn/" (or remove from documentation section) + +**Commit 4: Remove old file** + +- Delete docs/why-idempotency.md + +## Testing + +After implementation: + +1. Run `npm run dev` - verify site starts +2. Navigate to /learn/ - verify index loads +3. Check mermaid diagrams render in /learn/why +4. Verify YouTube video embed works +5. Test sidebar navigation: + - Click each item in learn sidebar + - Verify correct page loads +6. Test internal links: + - Click links between learn pages + - Verify they navigate correctly +7. Verify code examples display correctly with syntax highlighting +8. Run `npm run build` - verify production build succeeds +9. Run `npm run preview` - test production build locally + +## Success Criteria + +- All 5 learn pages accessible at /learn/\* paths +- Mermaid diagrams render correctly +- YouTube video embeds properly +- Navigation works for both desktop and mobile +- No broken links +- Production build succeeds diff --git a/docs/why-idempotency.md b/docs/why-idempotency.md deleted file mode 100644 index 3b334a2..0000000 --- a/docs/why-idempotency.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -prev: false -next: - text: "Specifications" - link: "/specs" ---- - -# Why Idempotency Matters - -In distributed systems, requests fail. Networks timeout, load balancers retry, users double-click. Without protection, these failures create duplicate transactions—double charges, duplicate orders, inconsistent state. - -## The Problem - -Duplicate requests happen more often than you'd think: - -| Cause | Example | -| ---------------- | ------------------------------------- | -| User behavior | Double-clicking a submit button | -| Client retries | Automatic retry on connection timeout | -| Network issues | Request succeeds but response is lost | -| Load balancers | Backend timeout triggers retry | -| Webhook delivery | Provider retries failed deliveries | - -Each duplicate request can create unintended side effects: duplicate payments, multiple orders, inconsistent data. - -## The Pattern - -Major APIs like Stripe and PayPal use a simple pattern to solve this: - -1. **Client generates a unique key** — typically a UUID for each unique operation -2. **Key sent as header** — `Idempotency-Key: ` -3. **Server stores key + response** — in your database or cache -4. **On duplicate request** — server returns cached response instead of reprocessing - -This makes any request safely retryable. The server either processes it once and caches the result, or recognizes the key and returns the previous result. - -## Benefits - -- **Fault tolerance**: Network interruptions don't cause duplicate transactions -- **Simplified retry logic**: Clients can safely retry without complex deduplication -- **Better UX**: Users don't wonder "did that go through?" -- **API reliability**: Stripe, PayPal, and major processors all use this pattern - -The IETF is standardizing this pattern in [draft-ietf-httpapi-idempotency-key-header-07](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-07). diff --git a/package-lock.json b/package-lock.json index a832ac1..ea59f59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "sitemap", + "name": "website", "lockfileVersion": 3, "requires": true, "packages": { @@ -14,7 +14,23 @@ "husky": "^9.1.7", "lint-staged": "^16.4.0", "prettier": "^3.8.1", - "vitepress": "^2.0.0-alpha.17" + "vitepress": "^2.0.0-alpha.17", + "vitepress-mermaid-renderer": "^1.1.20" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, "node_modules/@babel/code-frame": { @@ -82,6 +98,79 @@ "node": ">=6.9.0" } }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.1.2.tgz", + "integrity": "sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@chevrotain/gast": "11.1.2", + "@chevrotain/types": "11.1.2", + "lodash-es": "4.17.23" + } + }, + "node_modules/@chevrotain/cst-dts-gen/node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@chevrotain/gast": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.1.2.tgz", + "integrity": "sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@chevrotain/types": "11.1.2", + "lodash-es": "4.17.23" + } + }, + "node_modules/@chevrotain/gast/node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.1.2.tgz", + "integrity": "sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@chevrotain/types": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz", + "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@chevrotain/utils": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.1.2.tgz", + "integrity": "sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, "node_modules/@commitlint/cli": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.0.tgz", @@ -1025,6 +1114,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1032,6 +1134,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@mermaid-js/parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.0.tgz", + "integrity": "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "langium": "^4.0.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.2", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", @@ -1503,6 +1616,321 @@ "url": "https://ko-fi.com/dangreen" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -1517,6 +1945,14 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -1580,6 +2016,15 @@ "undici-types": "~7.18.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -1601,6 +2046,18 @@ "dev": true, "license": "ISC" }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.5.tgz", @@ -2037,6 +2494,44 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chevrotain": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.2.tgz", + "integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@chevrotain/cst-dts-gen": "11.1.2", + "@chevrotain/gast": "11.1.2", + "@chevrotain/regexp-to-ast": "11.1.2", + "@chevrotain/types": "11.1.2", + "@chevrotain/utils": "11.1.2", + "lodash-es": "4.17.23" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chevrotain/node_modules/lodash-es": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -2190,6 +2685,14 @@ "dot-prop": "^5.1.0" } }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/conventional-changelog-angular": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", @@ -2233,72 +2736,685 @@ "node": ">=18" } }, - "node_modules/cosmiconfig": { - "version": "9.0.1", + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", "dev": true, - "license": "MIT", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", + "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^2.6.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "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/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, + "license": "ISC", + "peer": true, "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": ">=12" }, "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "d3-selection": "2 - 3" } }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", - "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "dev": true, - "license": "MIT", + "license": "ISC", + "peer": true, "dependencies": { - "jiti": "^2.6.1" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": ">=v18" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=9", - "typescript": ">=5" + "node": ">=12" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/dagre-d3-es": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz", + "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "d3": "^7.9.0", + "lodash-es": "^4.17.21" } }, - "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==", + "node_modules/dayjs": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "4.4.3", @@ -2325,6 +3441,17 @@ "dev": true, "license": "MIT" }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2349,6 +3476,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/dompurify": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -2900,6 +4038,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "dev": true, + "license": "MIT", + "peer": true + }, "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", @@ -2972,6 +4118,20 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3040,6 +4200,17 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dev": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3168,6 +4339,35 @@ "dev": true, "license": "MIT" }, + "node_modules/katex": { + "version": "0.16.44", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.44.tgz", + "integrity": "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "peer": true, + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3178,6 +4378,40 @@ "json-buffer": "3.0.1" } }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "dev": true, + "peer": true + }, + "node_modules/langium": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.1.tgz", + "integrity": "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "chevrotain": "~11.1.1", + "chevrotain-allstar": "~0.3.1", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.1.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3342,6 +4576,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -3539,6 +4781,20 @@ "dev": true, "license": "MIT" }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "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", @@ -3574,6 +4830,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mermaid": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.14.0.tgz", + "integrity": "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.1.0", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.33.1", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.19", + "dompurify": "^3.3.1", + "katex": "^0.16.25", + "khroma": "^2.1.0", + "lodash-es": "^4.17.23", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, "node_modules/micromark-util-character": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", @@ -3714,6 +5001,20 @@ "dev": true, "license": "MIT" }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3832,6 +5133,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3864,6 +5173,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3884,6 +5201,14 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/perfect-debounce": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", @@ -3911,6 +5236,39 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/postcss": { "version": "8.5.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", @@ -4068,6 +5426,14 @@ "dev": true, "license": "MIT" }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "dev": true, + "license": "Unlicense", + "peer": true + }, "node_modules/rollup": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", @@ -4113,6 +5479,36 @@ "fsevents": "~2.3.2" } }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -4299,6 +5695,14 @@ "node": ">=8" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/tabbable": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", @@ -4344,6 +5748,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.10" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4372,6 +5787,14 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/undici-types": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", @@ -4463,6 +5886,21 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "peer": true, + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -4615,6 +6053,81 @@ } } }, + "node_modules/vitepress-mermaid-renderer": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/vitepress-mermaid-renderer/-/vitepress-mermaid-renderer-1.1.20.tgz", + "integrity": "sha512-lBe0KBkrTtXZIczNlwlVm7JVcrmCjSR7n5J3hEBg2K4/v5U12oW3MJ1hqh9cpY2avLKL66YBqxn3fJjey3zqWw==", + "dev": true, + "license": "GPL-3.0-only", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "mermaid": "^11.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/vue": { "version": "3.5.31", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.31.tgz", diff --git a/package.json b/package.json index 85a667f..cae6dac 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "husky": "^9.1.7", "lint-staged": "^16.4.0", "prettier": "^3.8.1", - "vitepress": "^2.0.0-alpha.17" + "vitepress": "^2.0.0-alpha.17", + "vitepress-mermaid-renderer": "^1.1.20" }, "scripts": { "dev": "vitepress dev",