diff --git a/.env.production.example b/.env.production.example
new file mode 100644
index 00000000..f8787bb1
--- /dev/null
+++ b/.env.production.example
@@ -0,0 +1,45 @@
+# =============================================================================
+# DTax Production Environment Variables
+# Copy this file to .env and fill in the values
+# =============================================================================
+
+# ---- Required ----
+DATABASE_URL="postgresql://dtax:CHANGE_ME@postgres:5432/dtax?schema=public"
+POSTGRES_PASSWORD=CHANGE_ME
+JWT_SECRET=CHANGE_ME_AT_LEAST_32_CHARACTERS_LONG
+# ENCRYPTION_KEY must be a 64-char hex string: run `openssl rand -hex 32`
+ENCRYPTION_KEY=CHANGE_ME_64_HEX_CHARS_RUN_openssl_rand_hex_32
+NODE_ENV=production
+
+# ---- URLs ----
+HOST=0.0.0.0
+PORT=3001
+CORS_ORIGIN=https://yourdomain.com
+APP_URL=https://yourdomain.com
+NEXT_PUBLIC_API_URL=https://yourdomain.com
+NEXT_PUBLIC_SITE_URL=https://yourdomain.com
+
+# ---- Email (Resend) ----
+RESEND_API_KEY=CHANGE_ME
+FROM_EMAIL=noreply@yourdomain.com
+
+# ---- Payments (Stripe) ----
+STRIPE_SECRET_KEY=CHANGE_ME
+STRIPE_WEBHOOK_SECRET=CHANGE_ME
+STRIPE_PRO_PRICE_ID=
+STRIPE_CPA_PRICE_ID=
+
+# ---- AI (Anthropic) ----
+ANTHROPIC_API_KEY=CHANGE_ME
+
+# ---- Blockchain Indexers ----
+ETHERSCAN_API_KEY=
+SOLSCAN_API_KEY=
+
+# ---- Analytics (PostHog) ----
+NEXT_PUBLIC_POSTHOG_KEY=
+NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
+
+# ---- Error Tracking (Sentry) ----
+SENTRY_DSN=
+SENTRY_AUTH_TOKEN=
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 16845127..8f4137b0 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -4,5 +4,5 @@ contact_links:
url: https://github.com/dTaxLab/dtax/discussions
about: Ask questions or share ideas
- name: Documentation
- url: https://dtax.dev
+ url: https://getdtax.com
about: Check the docs first
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..9996770e
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,99 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ test:
+ name: Test & Build
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [20, 22]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0
+
+ - name: Setup Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: "pnpm"
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build shared-types
+ run: pnpm --filter @dtax/shared-types run build
+
+ - name: Type check (tax-engine)
+ run: pnpm --filter @dtax/tax-engine exec tsc --noEmit
+
+ - name: Type check (cli)
+ run: pnpm --filter @dtax/cli exec tsc --noEmit
+
+ - name: Test (tax-engine)
+ run: pnpm --filter @dtax/tax-engine run test
+
+ - name: Test (cli)
+ run: pnpm --filter @dtax/cli run test
+
+ - name: Build (all packages)
+ run: pnpm run build
+
+ lint:
+ name: Lint & Format
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
+ with:
+ node-version: 20
+ cache: "pnpm"
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Check formatting
+ run: npx prettier --check "**/*.{ts,tsx,js,jsx,json,md}"
+
+ dependency-audit:
+ name: Dependency Audit
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
+ with:
+ node-version: 22
+ cache: "pnpm"
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Audit dependencies
+ run: pnpm audit --audit-level=high
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 70a1f12a..67194196 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -9,13 +9,14 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
publish:
runs-on: ubuntu-latest
+ if: github.repository != 'dTaxLab/dtax-private'
permissions:
contents: write
pull-requests: write
steps:
- - uses: actions/checkout@v4
- - uses: pnpm/action-setup@v4
- - uses: actions/setup-node@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0
+ - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 22
cache: pnpm
@@ -25,7 +26,7 @@ jobs:
- run: pnpm build
- name: Create Release PR or Publish
- uses: changesets/action@v1
+ uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
with:
publish: pnpm publish-packages
title: "chore: release packages"
diff --git a/.gitignore b/.gitignore
index f9d37506..0e18dd12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,5 @@ data/reports/
# Generated
*.tsbuildinfo
+apps/data/
+.maintenance
diff --git a/README.es.md b/README.es.md
new file mode 100644
index 00000000..2934cc9f
--- /dev/null
+++ b/README.es.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ El único motor completo de impuestos cripto en TypeScript disponible en npm
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23 parsers de exchanges** | **8 métodos de base de coste** — FIFO / LIFO / HIFO / UK Share Pooling / +4 más | **Form 8949 + Schedule D** | **Detección de wash sales** | **Simulador de escenarios**
+
+## Instalación
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## Ejemplo rápido
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. Parse any exchange CSV (auto-detects format)
+const { lots, events } = parseCsv(csvString);
+
+// 2. Calculate gains/losses
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. Generate IRS Form 8949
+const report = generateForm8949(results);
+```
+
+## CLI
+
+Calcula impuestos desde la línea de comandos sin escribir código:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+Instala globalmente para uso frecuente:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## Exchanges soportados (23 parsers)
+
+Todos los parsers detectan automáticamente el formato CSV. No requiere configuración.
+
+| Categoría | Exchanges |
+| ----------- | ----------------------------------------------------------------------------------- |
+| Principales | Coinbase, Binance, Binance US, Kraken, Gemini |
+| Globales | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| Otros | Crypto.com, Bitfinex, Poloniex |
+| On-chain | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| Migración | Koinly, CoinTracker, Cryptact (importar desde competidores) |
+| Genérico | Generic CSV (mapea tus propias columnas) |
+
+## Características
+
+- **8 métodos de base de coste** -- FIFO, LIFO, HIFO, Specific ID, UK Share Pooling, Germany FIFO, PMPA, Total Average (EE.UU. + internacional)
+- **Form 8949** -- Exportación en CSV, PDF y TXF (TurboTax) con clasificación Box A-F
+- **Schedule D** -- Agregación Part I/II, límite de pérdidas de $3,000, cálculo de arrastre
+- **Detección de wash sales** -- Ventana de 30 días, rechazo parcial, código W en Form 8949
+- **Simulador de escenarios** -- Previsualiza el impacto fiscal antes de vender (`simulateSale()`)
+- **Comparación de métodos** -- Encuentra el método óptimo entre FIFO/LIFO/HIFO (`compareAllMethods()`)
+- **Soporte DeFi + NFT** -- Depósitos/retiros de LP, staking, wraps, bridges, 12 tipos de transacciones DeFi
+- **Reconciliación 1099-DA** -- Coincidencia en 3 fases contra datos reportados por brokers
+- **Análisis de portafolio** -- Agregación de posiciones, P&L no realizado, oportunidades de tax-loss harvesting
+- **Contabilidad aislada por wallet** -- Aislamiento estricto de base de costo por wallet
+- **Detección de transferencias internas** -- Detección automática de transferencias entre tus propias wallets
+
+## Comparación con alternativas
+
+| Característica | dTax | Rotki | RP2 |
+| ------------------------------- | :--------: | :-----: | :------: |
+| Lenguaje | TypeScript | Python | Python |
+| Instalable vía npm | Yes | No | No |
+| Parsers de exchanges | 23 | 15 | 8 |
+| Métodos de base de costo | 8 | 3 | 3 |
+| Form 8949 PDF | Yes | No | No |
+| Exportación TXF TurboTax | Yes | No | No |
+| Generación de Schedule D | Yes | No | No |
+| Detección de wash sales | Yes | Yes | No |
+| Simulador de escenarios | Yes | No | No |
+| Comparación de métodos | Yes | No | No |
+| Tipos de tx DeFi/NFT | 12 | 8 | 4 |
+| Reconciliación 1099-DA | Yes | No | No |
+| Importación CSV de competidores | Yes | No | No |
+| Herramienta CLI | Yes | Yes | Yes |
+| Navegador/Node.js | Both | Desktop | CLI only |
+
+## Paquetes
+
+| Paquete | Descripción |
+| --------------------------------------------- | --------------------------------------------- |
+| [`@dtax/tax-engine`](packages/tax-engine) | Motor de cálculo principal, parsers, reportes |
+| [`@dtax/cli`](packages/cli) | Interfaz de línea de comandos |
+| [`@dtax/shared-types`](packages/shared-types) | Definiciones de tipos TypeScript |
+
+## Aspectos destacados de la API
+
+```typescript
+// Cost basis calculation
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// Reports
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// Analysis
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // what-if
+import { compareAllMethods } from "@dtax/tax-engine"; // optimizer
+import { analyzeHoldings } from "@dtax/tax-engine"; // portfolio
+
+// Parsers (auto-detect or use individually)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## Contribuir
+
+Las contribuciones son bienvenidas. Consulta [CONTRIBUTING.md](CONTRIBUTING.md) para las directrices.
+
+```bash
+# Prerequisites: Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 980+ tests across all packages
+pnpm build # build all packages
+```
+
+## Licencia
+
+Todos los paquetes en este repositorio están licenciados bajo [AGPL-3.0](LICENSE).
+
+Esto significa que puedes usar dTax libremente en tus proyectos. Si modificas el código fuente y lo distribuyes (incluyendo como un servicio en red), debes publicar tus modificaciones bajo AGPL-3.0.
+
+Para consultas sobre licencias comerciales: [getdtax.com](https://getdtax.com)
+
+## Enlaces
+
+- Sitio web: [getdtax.com](https://getdtax.com)
+- Problemas: [GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- Discusiones: [GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/README.ja.md b/README.ja.md
new file mode 100644
index 00000000..c4c12a73
--- /dev/null
+++ b/README.ja.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ npm で利用できる唯一の完全な TypeScript 暗号資産税務エンジン
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23 種の取引所パーサー** | **8つのコスト基準方式 — FIFO / LIFO / HIFO / UK Share Pooling / 他4種** | **Form 8949 + Schedule D** | **ウォッシュセール検出** | **What-if シミュレーター**
+
+## インストール
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## クイック例
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. 任意の取引所 CSV を解析(フォーマット自動検出)
+const { lots, events } = parseCsv(csvString);
+
+// 2. 損益を計算
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. IRS Form 8949 を生成
+const report = generateForm8949(results);
+```
+
+## CLI
+
+コードを書かずにコマンドラインから税金を計算できます:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+グローバルインストールして繰り返し使用:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## 対応取引所(23 パーサー)
+
+すべてのパーサーは CSV フォーマットを自動検出します。設定は不要です。
+
+| カテゴリ | 取引所 |
+| -------------- | ----------------------------------------------------------------------------------- |
+| 主要 | Coinbase, Binance, Binance US, Kraken, Gemini |
+| グローバル | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| その他 | Crypto.com, Bitfinex, Poloniex |
+| オンチェーン | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| 移行 | Koinly, CoinTracker, Cryptact(競合サービスからのインポート) |
+| フォールバック | Generic CSV(独自のカラムをマッピング) |
+
+## 機能
+
+- **8つのコスト基準方式** -- FIFO、LIFO、HIFO、Specific ID、UK Share Pooling、Germany FIFO、PMPA、Total Average(米国 + 海外対応)
+- **Form 8949** -- CSV、PDF、TXF(TurboTax)エクスポート、Box A-F 分類対応
+- **Schedule D** -- Part I/II 集計、$3,000 損失上限、繰越計算
+- **ウォッシュセール検出** -- 30 日間ウィンドウ、部分的否認、Form 8949 コード W
+- **What-if シミュレーター** -- 売却前に税金への影響をプレビュー(`simulateSale()`)
+- **方式比較** -- FIFO/LIFO/HIFO 全方式で最適な方式を検索(`compareAllMethods()`)
+- **DeFi + NFT 対応** -- LP 入出金、ステーキング、ラップ、ブリッジ、12 種類の DeFi トランザクションタイプ
+- **1099-DA 照合** -- ブローカー報告データとの 3 フェーズマッチング
+- **ポートフォリオ分析** -- 保有資産集計、未実現損益、タックスロスハーベスティング機会
+- **ウォレット分離会計** -- ウォレットごとの厳密な取得原価分離
+- **内部送金マッチング** -- 自分のウォレット間の送金を自動検出
+
+## 代替ツールとの比較
+
+| 機能 | dTax | Rotki | RP2 |
+| ------------------------------- | :--------: | :-----: | :------: |
+| 言語 | TypeScript | Python | Python |
+| npm インストール可能 | Yes | No | No |
+| 取引所パーサー | 23 | 15 | 8 |
+| 取得原価計算方式 | 8 | 3 | 3 |
+| Form 8949 PDF | Yes | No | No |
+| TurboTax TXF エクスポート | Yes | No | No |
+| Schedule D 生成 | Yes | No | No |
+| ウォッシュセール検出 | Yes | Yes | No |
+| What-if シミュレーター | Yes | No | No |
+| 方式比較 | Yes | No | No |
+| DeFi/NFT トランザクションタイプ | 12 | 8 | 4 |
+| 1099-DA 照合 | Yes | No | No |
+| 競合 CSV インポート | Yes | No | No |
+| CLI ツール | Yes | Yes | Yes |
+| ブラウザ/Node.js | Both | Desktop | CLI only |
+
+## パッケージ
+
+| パッケージ | 説明 |
+| --------------------------------------------- | ------------------------------------ |
+| [`@dtax/tax-engine`](packages/tax-engine) | コア計算エンジン、パーサー、レポート |
+| [`@dtax/cli`](packages/cli) | コマンドラインインターフェース |
+| [`@dtax/shared-types`](packages/shared-types) | TypeScript 型定義 |
+
+## API ハイライト
+
+```typescript
+// 取得原価計算
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// レポート
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// 分析
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // what-if
+import { compareAllMethods } from "@dtax/tax-engine"; // オプティマイザー
+import { analyzeHoldings } from "@dtax/tax-engine"; // ポートフォリオ
+
+// パーサー(自動検出または個別使用)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## コントリビューション
+
+コントリビューションを歓迎します。ガイドラインは [CONTRIBUTING.md](CONTRIBUTING.md) をご覧ください。
+
+```bash
+# 前提条件: Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 全パッケージで 980 以上のテスト
+pnpm build # 全パッケージをビルド
+```
+
+## ライセンス
+
+このリポジトリのすべてのパッケージは [AGPL-3.0](LICENSE) の下でライセンスされています。
+
+dTax はプロジェクトで自由にご利用いただけます。ソースコードを改変して配布する場合(ネットワークサービスとしての提供を含む)、改変部分を AGPL-3.0 の下で公開する必要があります。
+
+商用ライセンスに関するお問い合わせ: [getdtax.com](https://getdtax.com)
+
+## リンク
+
+- ウェブサイト: [getdtax.com](https://getdtax.com)
+- Issues: [GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- ディスカッション: [GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/README.ko.md b/README.ko.md
new file mode 100644
index 00000000..db252aac
--- /dev/null
+++ b/README.ko.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ npm에서 유일한 완전한 TypeScript 암호화폐 세금 엔진
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23개 거래소 파서** | **8가지 원가 기준 방법 — FIFO / LIFO / HIFO / UK Share Pooling / +4가지** | **Form 8949 + Schedule D** | **워시세일 감지** | **가상 매도 시뮬레이터**
+
+## 설치
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## 빠른 예제
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. 거래소 CSV 파싱 (형식 자동 감지)
+const { lots, events } = parseCsv(csvString);
+
+// 2. 자본이득/손실 계산
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. IRS Form 8949 생성
+const report = generateForm8949(results);
+```
+
+## CLI
+
+코드 작성 없이 커맨드 라인에서 세금을 계산하세요:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+반복 사용을 위해 전역 설치:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## 지원 거래소 (23개 파서)
+
+모든 파서가 CSV 형식을 자동 감지합니다. 별도의 설정이 필요 없습니다.
+
+| 분류 | 거래소 |
+| ------------ | ----------------------------------------------------------------------------------- |
+| 주요 | Coinbase, Binance, Binance US, Kraken, Gemini |
+| 글로벌 | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| 기타 | Crypto.com, Bitfinex, Poloniex |
+| 온체인 | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| 마이그레이션 | Koinly, CoinTracker, Cryptact (경쟁사에서 가져오기) |
+| 대체 | Generic CSV (직접 열 매핑) |
+
+## 주요 기능
+
+- **8가지 원가 기준 방법** -- FIFO, LIFO, HIFO, Specific ID, UK Share Pooling, Germany FIFO, PMPA, Total Average (미국 + 국제)
+- **Form 8949** -- CSV, PDF, TXF (TurboTax) 내보내기 및 Box A-F 분류
+- **Schedule D** -- Part I/II 합산, $3,000 손실 한도, 이월 계산
+- **워시세일 감지** -- 30일 기간, 부분 비허용, Form 8949 코드 W
+- **가상 매도 시뮬레이터** -- 매도 전 세금 영향 미리보기 (`simulateSale()`)
+- **방식 비교** -- FIFO/LIFO/HIFO 중 최적 방식 찾기 (`compareAllMethods()`)
+- **DeFi + NFT 지원** -- LP 예치/출금, 스테이킹, 랩핑, 브릿지, 12개 DeFi 거래 유형
+- **1099-DA 대사** -- 브로커 보고 데이터와 3단계 매칭
+- **포트폴리오 분석** -- 보유 자산 합산, 미실현 손익, 세금 손실 수확 기회
+- **지갑별 분리 회계** -- 지갑별 엄격한 원가 기준 분리
+- **내부 이체 매칭** -- 본인 소유 지갑 간 이체 자동 감지
+
+## 대안과의 비교
+
+| 기능 | dTax | Rotki | RP2 |
+| --------------------- | :--------: | :-----: | :------: |
+| 언어 | TypeScript | Python | Python |
+| npm 설치 가능 | Yes | No | No |
+| 거래소 파서 | 23 | 15 | 8 |
+| 원가 기준 방식 | 8 | 3 | 3 |
+| Form 8949 PDF | Yes | No | No |
+| TurboTax TXF 내보내기 | Yes | No | No |
+| Schedule D 생성 | Yes | No | No |
+| 워시세일 감지 | Yes | Yes | No |
+| 가상 매도 시뮬레이터 | Yes | No | No |
+| 방식 비교 | Yes | No | No |
+| DeFi/NFT 거래 유형 | 12 | 8 | 4 |
+| 1099-DA 대사 | Yes | No | No |
+| 경쟁사 CSV 가져오기 | Yes | No | No |
+| CLI 도구 | Yes | Yes | Yes |
+| 브라우저/Node.js | Both | Desktop | CLI only |
+
+## 패키지
+
+| 패키지 | 설명 |
+| --------------------------------------------- | ---------------------------- |
+| [`@dtax/tax-engine`](packages/tax-engine) | 핵심 계산 엔진, 파서, 보고서 |
+| [`@dtax/cli`](packages/cli) | 커맨드 라인 인터페이스 |
+| [`@dtax/shared-types`](packages/shared-types) | TypeScript 타입 정의 |
+
+## API 하이라이트
+
+```typescript
+// 원가 기준 계산
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// 보고서
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// 분석
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // 가상 매도
+import { compareAllMethods } from "@dtax/tax-engine"; // 최적화
+import { analyzeHoldings } from "@dtax/tax-engine"; // 포트폴리오
+
+// 파서 (자동 감지 또는 개별 사용)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## 기여하기
+
+기여를 환영합니다. 가이드라인은 [CONTRIBUTING.md](CONTRIBUTING.md)를 참고하세요.
+
+```bash
+# 필수 조건: Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 모든 패키지에 걸쳐 980개 이상의 테스트
+pnpm build # 모든 패키지 빌드
+```
+
+## 라이선스
+
+이 저장소의 모든 패키지는 [AGPL-3.0](LICENSE) 라이선스를 따릅니다.
+
+dTax를 프로젝트에서 자유롭게 사용할 수 있습니다. 소스를 수정하여 배포하는 경우 (네트워크 서비스 포함), 수정 사항을 AGPL-3.0으로 공개해야 합니다.
+
+상업용 라이선스 문의: [getdtax.com](https://getdtax.com)
+
+## 링크
+
+- 웹사이트: [getdtax.com](https://getdtax.com)
+- 이슈: [GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- 토론: [GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/README.md b/README.md
index 066ac43c..1a8f78b4 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
-
DTax
+
+ dTax
The only complete TypeScript crypto tax engine on npm
@@ -9,11 +10,14 @@
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
---
-**23 exchange parsers** | **FIFO / LIFO / HIFO / Specific ID** | **Form 8949 + Schedule D** | **Wash sale detection** | **What-if simulator**
+**23 exchange parsers** | **8 cost basis methods** — FIFO / LIFO / HIFO / UK Share Pooling / +4 more | **Form 8949 + Schedule D** | **Wash sale detection** | **What-if simulator**
## Install
@@ -75,7 +79,7 @@ All parsers auto-detect the CSV format. No configuration required.
## Features
-- **4 cost basis methods** -- FIFO, LIFO, HIFO, Specific ID (IRS-compliant)
+- **8 cost basis methods** -- FIFO, LIFO, HIFO, Specific ID, UK Share Pooling, Germany FIFO, PMPA, Total Average (US + international)
- **Form 8949** -- CSV, PDF, and TXF (TurboTax) export with Box A-F classification
- **Schedule D** -- Part I/II aggregation, $3,000 loss limit, carryover calculation
- **Wash sale detection** -- 30-day window, partial disallowance, Form 8949 code W
@@ -89,12 +93,12 @@ All parsers auto-detect the CSV format. No configuration required.
## Comparison with Alternatives
-| Feature | DTax | Rotki | RP2 |
+| Feature | dTax | Rotki | RP2 |
| ---------------------- | :--------: | :-----: | :------: |
| Language | TypeScript | Python | Python |
| npm installable | Yes | No | No |
| Exchange parsers | 23 | 15 | 8 |
-| Cost basis methods | 4 | 3 | 3 |
+| Cost basis methods | 8 | 3 | 3 |
| Form 8949 PDF | Yes | No | No |
| TurboTax TXF export | Yes | No | No |
| Schedule D generation | Yes | No | No |
@@ -148,7 +152,7 @@ Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
# Prerequisites: Node.js >= 20, pnpm >= 9
git clone https://github.com/dTaxLab/dtax.git && cd dtax
pnpm install
-pnpm test # 800+ tests across all packages
+pnpm test # 980+ tests across all packages
pnpm build # build all packages
```
@@ -156,7 +160,7 @@ pnpm build # build all packages
All packages in this repository are licensed under [AGPL-3.0](LICENSE).
-This means you can use DTax freely in your projects. If you modify the source and distribute it (including as a network service), you must release your modifications under AGPL-3.0.
+This means you can use dTax freely in your projects. If you modify the source and distribute it (including as a network service), you must release your modifications under AGPL-3.0.
For commercial licensing inquiries: [getdtax.com](https://getdtax.com)
diff --git a/README.pt.md b/README.pt.md
new file mode 100644
index 00000000..f7cf31ba
--- /dev/null
+++ b/README.pt.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ O único motor completo de impostos sobre criptomoedas em TypeScript no npm
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23 parsers de exchanges** | **8 métodos de base de custo — FIFO / LIFO / HIFO / UK Share Pooling / +4 mais** | **Form 8949 + Schedule D** | **Detecção de wash sale** | **Simulador what-if**
+
+## Instalação
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## Exemplo Rápido
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. Parse any exchange CSV (auto-detects format)
+const { lots, events } = parseCsv(csvString);
+
+// 2. Calculate gains/losses
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. Generate IRS Form 8949
+const report = generateForm8949(results);
+```
+
+## CLI
+
+Calcule impostos pela linha de comando sem escrever nenhum código:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+Instale globalmente para uso frequente:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## Exchanges Suportadas (23 Parsers)
+
+Todos os parsers detectam automaticamente o formato do CSV. Nenhuma configuração necessária.
+
+| Categoria | Exchanges |
+| ---------- | ----------------------------------------------------------------------------------- |
+| Principais | Coinbase, Binance, Binance US, Kraken, Gemini |
+| Globais | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| Outras | Crypto.com, Bitfinex, Poloniex |
+| On-chain | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| Migração | Koinly, CoinTracker, Cryptact (importação de concorrentes) |
+| Genérico | Generic CSV (mapeie suas próprias colunas) |
+
+## Funcionalidades
+
+- **8 métodos de base de custo** -- FIFO, LIFO, HIFO, Specific ID, UK Share Pooling, Germany FIFO, PMPA, Total Average (EUA + internacional)
+- **Form 8949** -- Exportação em CSV, PDF e TXF (TurboTax) com classificação Box A-F
+- **Schedule D** -- Agregação Parte I/II, limite de perda de $3.000, cálculo de compensação
+- **Detecção de wash sale** -- Janela de 30 dias, desqualificação parcial, código W no Form 8949
+- **Simulador what-if** -- Visualize o impacto fiscal antes de vender (`simulateSale()`)
+- **Comparação de métodos** -- Encontre o método ideal entre FIFO/LIFO/HIFO (`compareAllMethods()`)
+- **Suporte a DeFi + NFT** -- Depósitos/retiradas de LP, staking, wraps, bridges, 12 tipos de transação DeFi
+- **Reconciliação 1099-DA** -- Correspondência em 3 fases com dados reportados por corretoras
+- **Análise de portfólio** -- Agregação de posições, P&L não realizado, oportunidades de tax-loss harvesting
+- **Contabilidade isolada por carteira** -- Isolamento estrito do custo base por carteira
+- **Correspondência de transferências internas** -- Detecção automática de transferências entre suas próprias carteiras
+
+## Comparação com Alternativas
+
+| Funcionalidade | dTax | Rotki | RP2 |
+| --------------------------- | :--------: | :-----: | :--------: |
+| Linguagem | TypeScript | Python | Python |
+| Instalável via npm | Sim | Não | Não |
+| Parsers de exchanges | 23 | 15 | 8 |
+| Métodos de custo base | 8 | 3 | 3 |
+| Form 8949 PDF | Sim | Não | Não |
+| Exportação TXF TurboTax | Sim | Não | Não |
+| Geração de Schedule D | Sim | Não | Não |
+| Detecção de wash sale | Sim | Sim | Não |
+| Simulador what-if | Sim | Não | Não |
+| Comparação de métodos | Sim | Não | Não |
+| Tipos de tx DeFi/NFT | 12 | 8 | 4 |
+| Reconciliação 1099-DA | Sim | Não | Não |
+| Importação CSV concorrentes | Sim | Não | Não |
+| Ferramenta CLI | Sim | Sim | Sim |
+| Browser/Node.js | Ambos | Desktop | Apenas CLI |
+
+## Pacotes
+
+| Pacote | Descrição |
+| --------------------------------------------- | ----------------------------------------------- |
+| [`@dtax/tax-engine`](packages/tax-engine) | Motor de cálculo principal, parsers, relatórios |
+| [`@dtax/cli`](packages/cli) | Interface de linha de comando |
+| [`@dtax/shared-types`](packages/shared-types) | Definições de tipos TypeScript |
+
+## Destaques da API
+
+```typescript
+// Cost basis calculation
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// Reports
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// Analysis
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // what-if
+import { compareAllMethods } from "@dtax/tax-engine"; // optimizer
+import { analyzeHoldings } from "@dtax/tax-engine"; // portfolio
+
+// Parsers (auto-detect or use individually)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## Contribuindo
+
+Contribuições são bem-vindas. Consulte [CONTRIBUTING.md](CONTRIBUTING.md) para as diretrizes.
+
+```bash
+# Prerequisites: Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 980+ tests across all packages
+pnpm build # build all packages
+```
+
+## Licença
+
+Todos os pacotes neste repositório são licenciados sob [AGPL-3.0](LICENSE).
+
+Isso significa que você pode usar o dTax livremente em seus projetos. Se você modificar o código-fonte e distribuí-lo (incluindo como um serviço de rede), você deve disponibilizar suas modificações sob AGPL-3.0.
+
+Para consultas sobre licenciamento comercial: [getdtax.com](https://getdtax.com)
+
+## Links
+
+- Website: [getdtax.com](https://getdtax.com)
+- Issues: [GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- Discussões: [GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/README.zh-Hant.md b/README.zh-Hant.md
new file mode 100644
index 00000000..8282232d
--- /dev/null
+++ b/README.zh-Hant.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ npm 上唯一完整的 TypeScript 加密貨幣稅務引擎
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23 個交易所解析器** | **8 種成本基礎方法** — FIFO / LIFO / HIFO / UK Share Pooling / 等 4 種 | **Form 8949 + Schedule D** | **洗售偵測** | **模擬試算**
+
+## 安裝
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## 快速範例
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. 解析任何交易所的 CSV(自動偵測格式)
+const { lots, events } = parseCsv(csvString);
+
+// 2. 計算損益
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. 產生 IRS Form 8949
+const report = generateForm8949(results);
+```
+
+## CLI
+
+無需撰寫任何程式碼,直接從命令列計算稅務:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+全域安裝以便重複使用:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## 支援的交易所(23 個解析器)
+
+所有解析器皆自動偵測 CSV 格式,無需任何設定。
+
+| 類別 | 交易所 |
+| -------- | ----------------------------------------------------------------------------------- |
+| 主流 | Coinbase, Binance, Binance US, Kraken, Gemini |
+| 全球 | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| 其他 | Crypto.com, Bitfinex, Poloniex |
+| 鏈上 | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| 遷移匯入 | Koinly, CoinTracker, Cryptact(從競品匯入) |
+| 備用 | Generic CSV(自訂欄位對應) |
+
+## 功能特色
+
+- **8 種成本基礎方法** -- FIFO、LIFO、HIFO、Specific ID、UK Share Pooling、Germany FIFO、PMPA、Total Average(美國 + 國際)
+- **Form 8949** -- CSV、PDF 及 TXF(TurboTax)匯出,支援 Box A-F 分類
+- **Schedule D** -- Part I/II 彙總、$3,000 虧損上限、結轉計算
+- **洗售偵測** -- 30 天窗口期、部分不允許扣除、Form 8949 code W
+- **模擬試算** -- 出售前預覽稅務影響(`simulateSale()`)
+- **方法比較** -- 在 FIFO/LIFO/HIFO 中找出最佳方法(`compareAllMethods()`)
+- **DeFi + NFT 支援** -- LP 存取、質押、封裝、跨鏈橋接,12 種 DeFi 交易類型
+- **1099-DA 對帳** -- 3 階段與券商申報資料比對
+- **投資組合分析** -- 持倉彙總、未實現損益、稅損收割機會
+- **錢包隔離記帳** -- 嚴格的逐錢包成本基礎隔離
+- **內部轉帳比對** -- 自動偵測您自有錢包之間的轉帳
+
+## 與替代方案的比較
+
+| 功能 | dTax | Rotki | RP2 |
+| ----------------- | :--------: | :------: | :----: |
+| 語言 | TypeScript | Python | Python |
+| 可透過 npm 安裝 | 是 | 否 | 否 |
+| 交易所解析器 | 23 | 15 | 8 |
+| 成本基礎方法 | 8 | 3 | 3 |
+| Form 8949 PDF | 是 | 否 | 否 |
+| TurboTax TXF 匯出 | 是 | 否 | 否 |
+| Schedule D 產生 | 是 | 否 | 否 |
+| 洗售偵測 | 是 | 是 | 否 |
+| 模擬試算 | 是 | 否 | 否 |
+| 方法比較 | 是 | 否 | 否 |
+| DeFi/NFT 交易類型 | 12 | 8 | 4 |
+| 1099-DA 對帳 | 是 | 否 | 否 |
+| 競品 CSV 匯入 | 是 | 否 | 否 |
+| CLI 工具 | 是 | 是 | 是 |
+| 瀏覽器/Node.js | 兩者皆可 | 桌面應用 | 僅 CLI |
+
+## 套件
+
+| 套件 | 說明 |
+| --------------------------------------------- | -------------------------- |
+| [`@dtax/tax-engine`](packages/tax-engine) | 核心計算引擎、解析器、報表 |
+| [`@dtax/cli`](packages/cli) | 命令列介面 |
+| [`@dtax/shared-types`](packages/shared-types) | TypeScript 型別定義 |
+
+## API 重點功能
+
+```typescript
+// 成本基礎計算
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// 報表
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// 分析
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // 模擬試算
+import { compareAllMethods } from "@dtax/tax-engine"; // 最佳化
+import { analyzeHoldings } from "@dtax/tax-engine"; // 投資組合
+
+// 解析器(自動偵測或個別使用)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## 貢獻
+
+歡迎貢獻。請參閱 [CONTRIBUTING.md](CONTRIBUTING.md) 了解指引。
+
+```bash
+# 前置需求:Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 所有套件共 980+ 項測試
+pnpm build # 建置所有套件
+```
+
+## 授權條款
+
+本儲存庫中的所有套件皆以 [AGPL-3.0](LICENSE) 授權。
+
+這代表您可以自由地在專案中使用 dTax。若您修改原始碼並加以散布(包含作為網路服務提供),您必須以 AGPL-3.0 釋出您的修改內容。
+
+商業授權洽詢:[getdtax.com](https://getdtax.com)
+
+## 連結
+
+- 官方網站:[getdtax.com](https://getdtax.com)
+- 問題回報:[GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- 討論區:[GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/README.zh.md b/README.zh.md
new file mode 100644
index 00000000..9d0a9efa
--- /dev/null
+++ b/README.zh.md
@@ -0,0 +1,171 @@
+
+
+
dTax
+
+ npm 上唯一完整的 TypeScript 加密货币税务引擎
+
+
+
+
+
+
+
+
+ English · 简体中文 · 繁體中文 · Español · 日本語 · 한국어 · Português
+
+
+
+---
+
+**23 个交易所解析器** | **8 种成本基础方法** — FIFO / LIFO / HIFO / UK Share Pooling / 等 4 种 | **Form 8949 + Schedule D** | **洗售检测** | **假设模拟器**
+
+## 安装
+
+```bash
+npm install @dtax/tax-engine
+```
+
+## 快速示例
+
+```typescript
+import {
+ parseCsv,
+ CostBasisCalculator,
+ generateForm8949,
+} from "@dtax/tax-engine";
+
+// 1. Parse any exchange CSV (auto-detects format)
+const { lots, events } = parseCsv(csvString);
+
+// 2. Calculate gains/losses
+const calc = new CostBasisCalculator("FIFO");
+calc.addLots(lots);
+const results = events.map((e) => calc.calculate(e));
+
+// 3. Generate IRS Form 8949
+const report = generateForm8949(results);
+```
+
+## CLI
+
+无需编写任何代码,直接在命令行计算税务:
+
+```bash
+npx @dtax/cli calculate trades.csv --method FIFO
+npx @dtax/cli calculate trades.csv --method LIFO --year 2025 --json
+npx @dtax/cli calculate coinbase.csv binance.csv --method HIFO
+```
+
+全局安装以便反复使用:
+
+```bash
+npm install -g @dtax/cli
+dtax calculate trades.csv --method FIFO --form8949 report.csv
+dtax calculate trades.csv --schedule-d --include-wash-sales
+```
+
+## 支持的交易所(23 个解析器)
+
+所有解析器自动检测 CSV 格式,无需任何配置。
+
+| 类别 | 交易所 |
+| -------- | ----------------------------------------------------------------------------------- |
+| 主流 | Coinbase, Binance, Binance US, Kraken, Gemini |
+| 全球 | KuCoin, OKX, Bybit, Gate.io, Bitget, MEXC, HTX (Huobi) |
+| 其他 | Crypto.com, Bitfinex, Poloniex |
+| 链上 | Etherscan (ETH + ERC-20 + BSC/Polygon/Avalanche/Fantom), Solscan (SOL + SPL + DeFi) |
+| 迁移导入 | Koinly, CoinTracker, Cryptact(从竞品导入) |
+| 通用 | Generic CSV(自定义列映射) |
+
+## 功能特性
+
+- **8 种成本基础方法** -- FIFO、LIFO、HIFO、Specific ID、UK Share Pooling、Germany FIFO、PMPA、Total Average(美国 + 国际)
+- **Form 8949** -- CSV、PDF 和 TXF(TurboTax)导出,支持 Box A-F 分类
+- **Schedule D** -- Part I/II 汇总、$3,000 亏损限额、结转计算
+- **洗售检测** -- 30 天窗口期、部分不允许扣除、Form 8949 code W
+- **假设模拟器** -- 卖出前预览税务影响(`simulateSale()`)
+- **方法对比** -- 在 FIFO/LIFO/HIFO 中找到最优方法(`compareAllMethods()`)
+- **DeFi + NFT 支持** -- LP 存取、质押、封装、跨链桥、12 种 DeFi 交易类型
+- **1099-DA 对账** -- 3 阶段与券商报告数据匹配
+- **投资组合分析** -- 持仓汇总、未实现盈亏、税务亏损收割机会
+- **钱包隔离核算** -- 严格按钱包隔离成本基础
+- **内部转账匹配** -- 自动检测你自己钱包之间的转账
+
+## 与替代方案的对比
+
+| 功能特性 | dTax | Rotki | RP2 |
+| ----------------- | :--------: | :-----: | :------: |
+| 编程语言 | TypeScript | Python | Python |
+| 支持 npm 安装 | Yes | No | No |
+| 交易所解析器 | 23 | 15 | 8 |
+| 成本基础方法 | 8 | 3 | 3 |
+| Form 8949 PDF | Yes | No | No |
+| TurboTax TXF 导出 | Yes | No | No |
+| Schedule D 生成 | Yes | No | No |
+| 洗售检测 | Yes | Yes | No |
+| 假设模拟器 | Yes | No | No |
+| 方法对比 | Yes | No | No |
+| DeFi/NFT 交易类型 | 12 | 8 | 4 |
+| 1099-DA 对账 | Yes | No | No |
+| 竞品 CSV 导入 | Yes | No | No |
+| CLI 工具 | Yes | Yes | Yes |
+| 浏览器/Node.js | Both | Desktop | CLI only |
+
+## 包
+
+| 包 | 描述 |
+| --------------------------------------------- | -------------------------- |
+| [`@dtax/tax-engine`](packages/tax-engine) | 核心计算引擎、解析器、报表 |
+| [`@dtax/cli`](packages/cli) | 命令行界面 |
+| [`@dtax/shared-types`](packages/shared-types) | TypeScript 类型定义 |
+
+## API 亮点
+
+```typescript
+// Cost basis calculation
+import { calculateFIFO, calculateLIFO, calculateHIFO } from "@dtax/tax-engine";
+
+// Reports
+import {
+ generateForm8949,
+ form8949ToCsv,
+ generateForm8949Pdf,
+} from "@dtax/tax-engine";
+import { generateScheduleD } from "@dtax/tax-engine";
+import { form8949ToTxf } from "@dtax/tax-engine"; // TurboTax
+
+// Analysis
+import { detectWashSales } from "@dtax/tax-engine";
+import { simulateSale } from "@dtax/tax-engine"; // what-if
+import { compareAllMethods } from "@dtax/tax-engine"; // optimizer
+import { analyzeHoldings } from "@dtax/tax-engine"; // portfolio
+
+// Parsers (auto-detect or use individually)
+import { parseCsv, detectCsvFormat } from "@dtax/tax-engine";
+```
+
+## 贡献
+
+欢迎贡献。请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 了解贡献指南。
+
+```bash
+# Prerequisites: Node.js >= 20, pnpm >= 9
+git clone https://github.com/dTaxLab/dtax.git && cd dtax
+pnpm install
+pnpm test # 980+ tests across all packages
+pnpm build # build all packages
+```
+
+## 许可证
+
+本仓库中的所有包均采用 [AGPL-3.0](LICENSE) 许可证。
+
+这意味着你可以在项目中自由使用 dTax。如果你修改源代码并分发(包括作为网络服务),你必须在 AGPL-3.0 下发布你的修改。
+
+商业许可咨询:[getdtax.com](https://getdtax.com)
+
+## 链接
+
+- 官网:[getdtax.com](https://getdtax.com)
+- 问题反馈:[GitHub Issues](https://github.com/dTaxLab/dtax/issues)
+- 讨论:[GitHub Discussions](https://github.com/dTaxLab/dtax/discussions)
diff --git a/apps/docs-site/.gitignore b/apps/docs-site/.gitignore
new file mode 100644
index 00000000..ee1a1605
--- /dev/null
+++ b/apps/docs-site/.gitignore
@@ -0,0 +1,10 @@
+dist/
+node_modules/
+.astro/
+
+# wrangler files
+.wrangler
+.dev.vars*
+!.dev.vars.example
+.env*
+!.env.example
diff --git a/apps/docs-site/astro.config.mjs b/apps/docs-site/astro.config.mjs
new file mode 100644
index 00000000..a21ab44d
--- /dev/null
+++ b/apps/docs-site/astro.config.mjs
@@ -0,0 +1,79 @@
+import { defineConfig } from 'astro/config';
+import starlight from '@astrojs/starlight';
+
+import cloudflare from "@astrojs/cloudflare";
+
+export default defineConfig({
+ site: 'https://dtax.dev',
+
+ integrations: [
+ starlight({
+ title: 'dTax Developer Hub',
+ description: 'Open-source crypto tax engine. 23 exchange parsers, FIFO/LIFO/HIFO, Form 8949.',
+ defaultLocale: 'en',
+ locales: {
+ en: { label: 'English' },
+ 'zh-cn': { label: '简体中文', lang: 'zh-CN' },
+ ja: { label: '日本語' },
+ ko: { label: '한국어' },
+ de: { label: 'Deutsch' },
+ fr: { label: 'Français' },
+ es: { label: 'Español' },
+ },
+ logo: {
+ src: './src/assets/logo.png',
+ replacesTitle: false,
+ },
+ social: [
+ { icon: 'github', label: 'GitHub', href: 'https://github.com/dTaxLab/dtax' },
+ ],
+ customCss: ['./src/styles/custom.css'],
+ components: {
+ Footer: './src/components/Footer.astro',
+ },
+ sidebar: [
+ {
+ label: 'Getting Started',
+ items: [
+ { label: 'Introduction', slug: 'introduction' },
+ { label: 'Quick Start', slug: 'quickstart' },
+ ],
+ },
+ {
+ label: 'Tax Engine',
+ items: [
+ { label: 'Overview', slug: 'tax-engine/overview' },
+ { label: 'Exchange Parsers', slug: 'tax-engine/parsers' },
+ { label: 'Cost Basis Methods', slug: 'tax-engine/cost-basis' },
+ { label: 'Reports', slug: 'tax-engine/reports' },
+ ],
+ },
+ {
+ label: 'REST API',
+ items: [
+ { label: 'Overview', slug: 'api/overview' },
+ { label: 'Authentication', slug: 'api/authentication' },
+ ],
+ },
+ {
+ label: 'Resources',
+ items: [
+ { label: 'Self-Hosting', slug: 'resources/self-hosting' },
+ { label: 'CSV Format Guide', slug: 'resources/csv-format' },
+ { label: 'Open Core License', slug: 'resources/license' },
+ { label: 'FAQ', slug: 'resources/faq' },
+ ],
+ },
+ ],
+ head: [
+ {
+ tag: 'meta',
+ attrs: { property: 'og:image', content: 'https://dtax.dev/og.png' },
+ },
+ ],
+ }),
+ ],
+
+ output: 'static',
+ adapter: cloudflare()
+});
\ No newline at end of file
diff --git a/apps/docs-site/functions/_middleware.js b/apps/docs-site/functions/_middleware.js
new file mode 100644
index 00000000..c6314675
--- /dev/null
+++ b/apps/docs-site/functions/_middleware.js
@@ -0,0 +1,39 @@
+export async function onRequest(context) {
+ const { request, next } = context;
+ const url = new URL(request.url);
+
+ // Only intercept root path
+ if (url.pathname !== "/") {
+ return next();
+ }
+
+ const acceptLanguage = request.headers.get("Accept-Language") || "";
+ const locale = detectLocale(acceptLanguage);
+
+ return Response.redirect(`${url.origin}/${locale}/`, 302);
+}
+
+function detectLocale(acceptLanguage) {
+ if (!acceptLanguage) return "en";
+
+ // Parse "zh-CN,zh;q=0.9,en;q=0.8" into sorted list
+ const langs = acceptLanguage
+ .split(",")
+ .map((entry) => {
+ const [code, q] = entry.trim().split(";q=");
+ return { code: code.trim().toLowerCase(), q: parseFloat(q ?? "1") };
+ })
+ .sort((a, b) => b.q - a.q);
+
+ for (const { code } of langs) {
+ if (code.startsWith("zh")) return "zh-cn";
+ if (code.startsWith("ja")) return "ja";
+ if (code.startsWith("ko")) return "ko";
+ if (code.startsWith("de")) return "de";
+ if (code.startsWith("fr")) return "fr";
+ if (code.startsWith("es")) return "es";
+ if (code.startsWith("en")) return "en";
+ }
+
+ return "en";
+}
diff --git a/apps/docs-site/package-lock.json b/apps/docs-site/package-lock.json
new file mode 100644
index 00000000..cab559d0
--- /dev/null
+++ b/apps/docs-site/package-lock.json
@@ -0,0 +1,10600 @@
+{
+ "name": "@dtax/docs-site",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@dtax/docs-site",
+ "version": "0.0.1",
+ "dependencies": {
+ "@astrojs/cloudflare": "^12.6.13",
+ "@astrojs/starlight": "^0.33.0",
+ "astro": "^5.0.0",
+ "sharp": "^0.33.5",
+ "typescript": "^5.9.3",
+ "zod": "^3.25.76"
+ },
+ "devDependencies": {
+ "@astrojs/check": "^0.9.8",
+ "wrangler": "^4.77.0"
+ }
+ },
+ "node_modules/@astrojs/check": {
+ "version": "0.9.8",
+ "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.8.tgz",
+ "integrity": "sha512-LDng8446QLS5ToKjRHd3bgUdirvemVVExV7nRyJfW2wV36xuv7vDxwy5NWN9zqeSEDgg0Tv84sP+T3yEq+Zlkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/language-server": "^2.16.5",
+ "chokidar": "^4.0.3",
+ "kleur": "^4.1.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "astro-check": "bin/astro-check.js"
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0"
+ }
+ },
+ "node_modules/@astrojs/check/node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@astrojs/check/node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@astrojs/check/node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@astrojs/cloudflare": {
+ "version": "12.6.13",
+ "resolved": "https://registry.npmjs.org/@astrojs/cloudflare/-/cloudflare-12.6.13.tgz",
+ "integrity": "sha512-oKaCyiovyQr183r9U93787Ju1zwk+rRMgPnLTwCLckHmOUK7sltA1Gp4LSGt8oNMgqQS6jR7uRdfQ/NPul37QA==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/internal-helpers": "0.7.6",
+ "@astrojs/underscore-redirects": "1.0.0",
+ "@cloudflare/workers-types": "^4.20260116.0",
+ "tinyglobby": "^0.2.15",
+ "vite": "^6.4.1",
+ "wrangler": "4.59.2"
+ },
+ "peerDependencies": {
+ "astro": "^5.7.0"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/unenv-preset": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.10.0.tgz",
+ "integrity": "sha512-/uII4vLQXhzCAZzEVeYAjFLBNg2nqTJ1JGzd2lRF6ItYe6U2zVoYGfeKpGx/EkBF6euiU+cyBXgMdtJih+nQ6g==",
+ "license": "MIT OR Apache-2.0",
+ "peerDependencies": {
+ "unenv": "2.0.0-rc.24",
+ "workerd": "^1.20251221.0"
+ },
+ "peerDependenciesMeta": {
+ "workerd": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/workerd-darwin-64": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260114.0.tgz",
+ "integrity": "sha512-HNlsRkfNgardCig2P/5bp/dqDECsZ4+NU5XewqArWxMseqt3C5daSuptI620s4pn7Wr0ZKg7jVLH0PDEBkA+aA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/workerd-darwin-arm64": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260114.0.tgz",
+ "integrity": "sha512-qyE1UdFnAlxzb+uCfN/d9c8icch7XRiH49/DjoqEa+bCDihTuRS7GL1RmhVIqHJhb3pX3DzxmKgQZBDBL83Inw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/workerd-linux-64": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260114.0.tgz",
+ "integrity": "sha512-Z0BLvAj/JPOabzads2ddDEfgExWTlD22pnwsuNbPwZAGTSZeQa3Y47eGUWyHk+rSGngknk++S7zHTGbKuG7RRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/workerd-linux-arm64": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260114.0.tgz",
+ "integrity": "sha512-kPUmEtUxUWlr9PQ64kuhdK0qyo8idPe5IIXUgi7xCD7mDd6EOe5J7ugDpbfvfbYKEjx4DpLvN2t45izyI/Sodw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@cloudflare/workerd-windows-64": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260114.0.tgz",
+ "integrity": "sha512-MJnKgm6i1jZGyt2ZHQYCnRlpFTEZcK2rv9y7asS3KdVEXaDgGF8kOns5u6YL6/+eMogfZuHRjfDS+UqRTUYIFA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz",
+ "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/android-arm": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz",
+ "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/android-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz",
+ "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/android-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz",
+ "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz",
+ "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz",
+ "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz",
+ "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-arm": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz",
+ "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz",
+ "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz",
+ "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz",
+ "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz",
+ "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz",
+ "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz",
+ "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz",
+ "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/linux-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz",
+ "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz",
+ "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz",
+ "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz",
+ "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz",
+ "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz",
+ "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz",
+ "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@esbuild/win32-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz",
+ "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/esbuild": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz",
+ "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.0",
+ "@esbuild/android-arm": "0.27.0",
+ "@esbuild/android-arm64": "0.27.0",
+ "@esbuild/android-x64": "0.27.0",
+ "@esbuild/darwin-arm64": "0.27.0",
+ "@esbuild/darwin-x64": "0.27.0",
+ "@esbuild/freebsd-arm64": "0.27.0",
+ "@esbuild/freebsd-x64": "0.27.0",
+ "@esbuild/linux-arm": "0.27.0",
+ "@esbuild/linux-arm64": "0.27.0",
+ "@esbuild/linux-ia32": "0.27.0",
+ "@esbuild/linux-loong64": "0.27.0",
+ "@esbuild/linux-mips64el": "0.27.0",
+ "@esbuild/linux-ppc64": "0.27.0",
+ "@esbuild/linux-riscv64": "0.27.0",
+ "@esbuild/linux-s390x": "0.27.0",
+ "@esbuild/linux-x64": "0.27.0",
+ "@esbuild/netbsd-arm64": "0.27.0",
+ "@esbuild/netbsd-x64": "0.27.0",
+ "@esbuild/openbsd-arm64": "0.27.0",
+ "@esbuild/openbsd-x64": "0.27.0",
+ "@esbuild/openharmony-arm64": "0.27.0",
+ "@esbuild/sunos-x64": "0.27.0",
+ "@esbuild/win32-arm64": "0.27.0",
+ "@esbuild/win32-ia32": "0.27.0",
+ "@esbuild/win32-x64": "0.27.0"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/miniflare": {
+ "version": "4.20260114.0",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260114.0.tgz",
+ "integrity": "sha512-QwHT7S6XqGdQxIvql1uirH/7/i3zDEt0B/YBXTYzMfJtVCR4+ue3KPkU+Bl0zMxvpgkvjh9+eCHhJbKEqya70A==",
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "0.8.1",
+ "sharp": "^0.34.5",
+ "undici": "7.14.0",
+ "workerd": "1.20260114.0",
+ "ws": "8.18.0",
+ "youch": "4.1.0-beta.10",
+ "zod": "^3.25.76"
+ },
+ "bin": {
+ "miniflare": "bootstrap.js"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/undici": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz",
+ "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/workerd": {
+ "version": "1.20260114.0",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260114.0.tgz",
+ "integrity": "sha512-kTJ+jNdIllOzWuVA3NRQRvywP0T135zdCjAE2dAUY1BFbxM6fmMZV8BbskEoQ4hAODVQUfZQmyGctcwvVCKxFA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "workerd": "bin/workerd"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "@cloudflare/workerd-darwin-64": "1.20260114.0",
+ "@cloudflare/workerd-darwin-arm64": "1.20260114.0",
+ "@cloudflare/workerd-linux-64": "1.20260114.0",
+ "@cloudflare/workerd-linux-arm64": "1.20260114.0",
+ "@cloudflare/workerd-windows-64": "1.20260114.0"
+ }
+ },
+ "node_modules/@astrojs/cloudflare/node_modules/wrangler": {
+ "version": "4.59.2",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.59.2.tgz",
+ "integrity": "sha512-Z4xn6jFZTaugcOKz42xvRAYKgkVUERHVbuCJ5+f+gK+R6k12L02unakPGOA0L0ejhUl16dqDjKe4tmL9sedHcw==",
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@cloudflare/kv-asset-handler": "0.4.2",
+ "@cloudflare/unenv-preset": "2.10.0",
+ "blake3-wasm": "2.1.5",
+ "esbuild": "0.27.0",
+ "miniflare": "4.20260114.0",
+ "path-to-regexp": "6.3.0",
+ "unenv": "2.0.0-rc.24",
+ "workerd": "1.20260114.0"
+ },
+ "bin": {
+ "wrangler": "bin/wrangler.js",
+ "wrangler2": "bin/wrangler.js"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@cloudflare/workers-types": "^4.20260114.0"
+ },
+ "peerDependenciesMeta": {
+ "@cloudflare/workers-types": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@astrojs/compiler": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz",
+ "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==",
+ "license": "MIT"
+ },
+ "node_modules/@astrojs/internal-helpers": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.6.tgz",
+ "integrity": "sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==",
+ "license": "MIT"
+ },
+ "node_modules/@astrojs/language-server": {
+ "version": "2.16.6",
+ "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.6.tgz",
+ "integrity": "sha512-N990lu+HSFiG57owR0XBkr02BYMgiLCshLf+4QG4v6jjSWkBeQGnzqi+E1L08xFPPJ7eEeXnxPXGLaVv5pa4Ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/compiler": "^2.13.1",
+ "@astrojs/yaml2ts": "^0.2.3",
+ "@jridgewell/sourcemap-codec": "^1.5.5",
+ "@volar/kit": "~2.4.28",
+ "@volar/language-core": "~2.4.28",
+ "@volar/language-server": "~2.4.28",
+ "@volar/language-service": "~2.4.28",
+ "muggle-string": "^0.4.1",
+ "tinyglobby": "^0.2.15",
+ "volar-service-css": "0.0.70",
+ "volar-service-emmet": "0.0.70",
+ "volar-service-html": "0.0.70",
+ "volar-service-prettier": "0.0.70",
+ "volar-service-typescript": "0.0.70",
+ "volar-service-typescript-twoslash-queries": "0.0.70",
+ "volar-service-yaml": "0.0.70",
+ "vscode-html-languageservice": "^5.6.2",
+ "vscode-uri": "^3.1.0"
+ },
+ "bin": {
+ "astro-ls": "bin/nodeServer.js"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.0",
+ "prettier-plugin-astro": ">=0.11.0"
+ },
+ "peerDependenciesMeta": {
+ "prettier": {
+ "optional": true
+ },
+ "prettier-plugin-astro": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@astrojs/markdown-remark": {
+ "version": "6.3.11",
+ "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.11.tgz",
+ "integrity": "sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/internal-helpers": "0.7.6",
+ "@astrojs/prism": "3.3.0",
+ "github-slugger": "^2.0.0",
+ "hast-util-from-html": "^2.0.3",
+ "hast-util-to-text": "^4.0.2",
+ "import-meta-resolve": "^4.2.0",
+ "js-yaml": "^4.1.1",
+ "mdast-util-definitions": "^6.0.0",
+ "rehype-raw": "^7.0.0",
+ "rehype-stringify": "^10.0.1",
+ "remark-gfm": "^4.0.1",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.2",
+ "remark-smartypants": "^3.0.2",
+ "shiki": "^3.21.0",
+ "smol-toml": "^1.6.0",
+ "unified": "^11.0.5",
+ "unist-util-remove-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "unist-util-visit-parents": "^6.0.2",
+ "vfile": "^6.0.3"
+ }
+ },
+ "node_modules/@astrojs/mdx": {
+ "version": "4.3.14",
+ "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.14.tgz",
+ "integrity": "sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/markdown-remark": "6.3.11",
+ "@mdx-js/mdx": "^3.1.1",
+ "acorn": "^8.15.0",
+ "es-module-lexer": "^1.7.0",
+ "estree-util-visit": "^2.0.0",
+ "hast-util-to-html": "^9.0.5",
+ "piccolore": "^0.1.3",
+ "rehype-raw": "^7.0.0",
+ "remark-gfm": "^4.0.1",
+ "remark-smartypants": "^3.0.2",
+ "source-map": "^0.7.6",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.3"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ },
+ "peerDependencies": {
+ "astro": "^5.0.0"
+ }
+ },
+ "node_modules/@astrojs/prism": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz",
+ "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "prismjs": "^1.30.0"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ }
+ },
+ "node_modules/@astrojs/sitemap": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.1.tgz",
+ "integrity": "sha512-IzQqdTeskaMX+QDZCzMuJIp8A8C1vgzMBp/NmHNnadepHYNHcxQdGLQZYfkbd2EbRXUfOS+UDIKx8sKg0oWVdw==",
+ "license": "MIT",
+ "dependencies": {
+ "sitemap": "^9.0.0",
+ "stream-replace-string": "^2.0.0",
+ "zod": "^4.3.6"
+ }
+ },
+ "node_modules/@astrojs/sitemap/node_modules/zod": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
+ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/@astrojs/starlight": {
+ "version": "0.33.2",
+ "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.33.2.tgz",
+ "integrity": "sha512-UpvPBMtZrP/x17uQmdOxm8lUTtmEJ0csTprQT8fd8HSHDn/pSK69fOsSjl6tk83ROMOARC5/DivExSxxJADNSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/mdx": "^4.2.3",
+ "@astrojs/sitemap": "^3.3.0",
+ "@pagefind/default-ui": "^1.3.0",
+ "@types/hast": "^3.0.4",
+ "@types/js-yaml": "^4.0.9",
+ "@types/mdast": "^4.0.4",
+ "astro-expressive-code": "^0.41.1",
+ "bcp-47": "^2.1.0",
+ "hast-util-from-html": "^2.0.1",
+ "hast-util-select": "^6.0.2",
+ "hast-util-to-string": "^3.0.0",
+ "hastscript": "^9.0.0",
+ "i18next": "^23.11.5",
+ "js-yaml": "^4.1.0",
+ "klona": "^2.0.6",
+ "mdast-util-directive": "^3.0.0",
+ "mdast-util-to-markdown": "^2.1.0",
+ "mdast-util-to-string": "^4.0.0",
+ "pagefind": "^1.3.0",
+ "rehype": "^13.0.1",
+ "rehype-format": "^5.0.0",
+ "remark-directive": "^3.0.0",
+ "unified": "^11.0.5",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.2"
+ },
+ "peerDependencies": {
+ "astro": "^5.1.5"
+ }
+ },
+ "node_modules/@astrojs/telemetry": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz",
+ "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ci-info": "^4.2.0",
+ "debug": "^4.4.0",
+ "dlv": "^1.1.3",
+ "dset": "^3.1.4",
+ "is-docker": "^3.0.0",
+ "is-wsl": "^3.1.0",
+ "which-pm-runs": "^1.1.0"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0"
+ }
+ },
+ "node_modules/@astrojs/underscore-redirects": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@astrojs/underscore-redirects/-/underscore-redirects-1.0.0.tgz",
+ "integrity": "sha512-qZxHwVnmb5FXuvRsaIGaqWgnftjCuMY+GSbaVZdBmE4j8AfgPqKPxYp8SUERyJcjpKCEmO4wD6ybuGH8A2kVRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@astrojs/yaml2ts": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.3.tgz",
+ "integrity": "sha512-PJzRmgQzUxI2uwpdX2lXSHtP4G8ocp24/t+bZyf5Fy0SZLSF9f9KXZoMlFM/XCGue+B0nH/2IZ7FpBYQATBsCg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yaml": "^2.8.2"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@capsizecss/unpack": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz",
+ "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cloudflare/kv-asset-handler": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz",
+ "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==",
+ "license": "MIT OR Apache-2.0",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@cloudflare/unenv-preset": {
+ "version": "2.16.0",
+ "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.0.tgz",
+ "integrity": "sha512-8ovsRpwzPoEqPUzoErAYVv8l3FMZNeBVQfJTvtzP4AgLSRGZISRfuChFxHWUQd3n6cnrwkuTGxT+2cGo8EsyYg==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0",
+ "peerDependencies": {
+ "unenv": "2.0.0-rc.24",
+ "workerd": "1.20260301.1 || ~1.20260302.1 || ~1.20260303.1 || ~1.20260304.1 || >1.20260305.0 <2.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "workerd": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-64": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260317.1.tgz",
+ "integrity": "sha512-8hjh3sPMwY8M/zedq3/sXoA2Q4BedlGufn3KOOleIG+5a4ReQKLlUah140D7J6zlKmYZAFMJ4tWC7hCuI/s79g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-darwin-arm64": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260317.1.tgz",
+ "integrity": "sha512-M/MnNyvO5HMgoIdr3QHjdCj2T1ki9gt0vIUnxYxBu9ISXS/jgtMl6chUVPJ7zHYBn9MyYr8ByeN6frjYxj0MGg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-64": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260317.1.tgz",
+ "integrity": "sha512-1ltuEjkRcS3fsVF7CxsKlWiRmzq2ZqMfqDN0qUOgbUwkpXsLVJsXmoblaLf5OP00ELlcgF0QsN0p2xPEua4Uug==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-linux-arm64": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260317.1.tgz",
+ "integrity": "sha512-3QrNnPF1xlaNwkHpasvRvAMidOvQs2NhXQmALJrEfpIJ/IDL2la8g499yXp3eqhG3hVMCB07XVY149GTs42Xtw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workerd-windows-64": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260317.1.tgz",
+ "integrity": "sha512-MfZTz+7LfuIpMGTa3RLXHX8Z/pnycZLItn94WRdHr8LPVet+C5/1Nzei399w/jr3+kzT4pDKk26JF/tlI5elpQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@cloudflare/workers-types": {
+ "version": "4.20260317.1",
+ "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260317.1.tgz",
+ "integrity": "sha512-+G4eVwyCpm8Au1ex8vQBCuA9wnwqetz4tPNRoB/53qvktERWBRMQnrtvC1k584yRE3emMThtuY0gWshvSJ++PQ==",
+ "license": "MIT OR Apache-2.0"
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@ctrl/tinycolor": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
+ "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@emmetio/abbreviation": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz",
+ "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@emmetio/scanner": "^1.0.4"
+ }
+ },
+ "node_modules/@emmetio/css-abbreviation": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz",
+ "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@emmetio/scanner": "^1.0.4"
+ }
+ },
+ "node_modules/@emmetio/css-parser": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@emmetio/css-parser/-/css-parser-0.4.1.tgz",
+ "integrity": "sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@emmetio/stream-reader": "^2.2.0",
+ "@emmetio/stream-reader-utils": "^0.1.0"
+ }
+ },
+ "node_modules/@emmetio/html-matcher": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@emmetio/html-matcher/-/html-matcher-1.3.0.tgz",
+ "integrity": "sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@emmetio/scanner": "^1.0.0"
+ }
+ },
+ "node_modules/@emmetio/scanner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz",
+ "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@emmetio/stream-reader": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz",
+ "integrity": "sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@emmetio/stream-reader-utils": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@emmetio/stream-reader-utils/-/stream-reader-utils-0.1.0.tgz",
+ "integrity": "sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz",
+ "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
+ "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
+ "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
+ "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
+ "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
+ "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
+ "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
+ "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
+ "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
+ "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
+ "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
+ "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
+ "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
+ "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
+ "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
+ "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
+ "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
+ "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
+ "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
+ "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
+ "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
+ "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@expressive-code/core": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.7.tgz",
+ "integrity": "sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ctrl/tinycolor": "^4.0.4",
+ "hast-util-select": "^6.0.2",
+ "hast-util-to-html": "^9.0.1",
+ "hast-util-to-text": "^4.0.1",
+ "hastscript": "^9.0.0",
+ "postcss": "^8.4.38",
+ "postcss-nested": "^6.0.1",
+ "unist-util-visit": "^5.0.0",
+ "unist-util-visit-parents": "^6.0.1"
+ }
+ },
+ "node_modules/@expressive-code/plugin-frames": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.7.tgz",
+ "integrity": "sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.7"
+ }
+ },
+ "node_modules/@expressive-code/plugin-shiki": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.7.tgz",
+ "integrity": "sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.7",
+ "shiki": "^3.2.2"
+ }
+ },
+ "node_modules/@expressive-code/plugin-text-markers": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.7.tgz",
+ "integrity": "sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.7"
+ }
+ },
+ "node_modules/@img/colour": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
+ "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
+ "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
+ "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
+ "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
+ "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
+ "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
+ "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
+ "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
+ "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
+ "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
+ "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.0.5"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
+ "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-ppc64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
+ "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
+ "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
+ "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
+ "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
+ "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
+ "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
+ "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@mdx-js/mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz",
+ "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdx": "^2.0.0",
+ "acorn": "^8.0.0",
+ "collapse-white-space": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-util-scope": "^1.0.0",
+ "estree-walker": "^3.0.0",
+ "hast-util-to-jsx-runtime": "^2.0.0",
+ "markdown-extensions": "^2.0.0",
+ "recma-build-jsx": "^1.0.0",
+ "recma-jsx": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "rehype-recma": "^1.0.0",
+ "remark-mdx": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.0.0",
+ "source-map": "^0.7.0",
+ "unified": "^11.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@oslojs/encoding": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
+ "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
+ "license": "MIT"
+ },
+ "node_modules/@pagefind/darwin-arm64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz",
+ "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@pagefind/darwin-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz",
+ "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@pagefind/default-ui": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz",
+ "integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==",
+ "license": "MIT"
+ },
+ "node_modules/@pagefind/freebsd-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz",
+ "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@pagefind/linux-arm64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz",
+ "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/linux-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz",
+ "integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@pagefind/windows-x64": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz",
+ "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@poppinss/colors": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz",
+ "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^4.1.5"
+ }
+ },
+ "node_modules/@poppinss/colors/node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@poppinss/dumper": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz",
+ "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@sindresorhus/is": "^7.0.2",
+ "supports-color": "^10.0.0"
+ }
+ },
+ "node_modules/@poppinss/exception": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz",
+ "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
+ "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+ "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+ "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+ "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+ "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+ "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+ "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+ "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+ "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+ "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+ "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+ "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+ "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+ "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+ "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+ "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+ "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+ "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+ "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+ "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+ "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+ "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+ "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+ "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+ "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@shikijs/core": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz",
+ "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.23.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.5"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz",
+ "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.23.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^4.3.4"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz",
+ "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.23.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz",
+ "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.23.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz",
+ "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.23.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz",
+ "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "license": "MIT"
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz",
+ "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@speed-highlight/core": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz",
+ "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/@types/debug": {
+ "version": "4.1.13",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
+ "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/js-yaml": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdx": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz",
+ "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/nlcst": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz",
+ "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "24.12.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
+ "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/sax": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
+ "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "license": "ISC"
+ },
+ "node_modules/@volar/kit": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.28.tgz",
+ "integrity": "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-service": "2.4.28",
+ "@volar/typescript": "2.4.28",
+ "typesafe-path": "^0.2.2",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ }
+ },
+ "node_modules/@volar/language-core": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz",
+ "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/source-map": "2.4.28"
+ }
+ },
+ "node_modules/@volar/language-server": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.28.tgz",
+ "integrity": "sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-core": "2.4.28",
+ "@volar/language-service": "2.4.28",
+ "@volar/typescript": "2.4.28",
+ "path-browserify": "^1.0.1",
+ "request-light": "^0.7.0",
+ "vscode-languageserver": "^9.0.1",
+ "vscode-languageserver-protocol": "^3.17.5",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "node_modules/@volar/language-service": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.28.tgz",
+ "integrity": "sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-core": "2.4.28",
+ "vscode-languageserver-protocol": "^3.17.5",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "node_modules/@volar/source-map": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz",
+ "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@volar/typescript": {
+ "version": "2.4.28",
+ "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz",
+ "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-core": "2.4.28",
+ "path-browserify": "^1.0.1",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "node_modules/@vscode/emmet-helper": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@vscode/emmet-helper/-/emmet-helper-2.11.0.tgz",
+ "integrity": "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emmet": "^2.4.3",
+ "jsonc-parser": "^2.3.0",
+ "vscode-languageserver-textdocument": "^1.0.1",
+ "vscode-languageserver-types": "^3.15.1",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "node_modules/@vscode/l10n": {
+ "version": "0.0.18",
+ "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz",
+ "integrity": "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
+ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-draft-04": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
+ "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "ajv": "^8.5.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/ansi-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/anymatch/node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-iterate": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz",
+ "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/astring": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz",
+ "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==",
+ "license": "MIT",
+ "bin": {
+ "astring": "bin/astring"
+ }
+ },
+ "node_modules/astro": {
+ "version": "5.18.1",
+ "resolved": "https://registry.npmjs.org/astro/-/astro-5.18.1.tgz",
+ "integrity": "sha512-m4VWilWZ+Xt6NPoYzC4CgGZim/zQUO7WFL0RHCH0AiEavF1153iC3+me2atDvXpf/yX4PyGUeD8wZLq1cirT3g==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/compiler": "^2.13.0",
+ "@astrojs/internal-helpers": "0.7.6",
+ "@astrojs/markdown-remark": "6.3.11",
+ "@astrojs/telemetry": "3.3.0",
+ "@capsizecss/unpack": "^4.0.0",
+ "@oslojs/encoding": "^1.1.0",
+ "@rollup/pluginutils": "^5.3.0",
+ "acorn": "^8.15.0",
+ "aria-query": "^5.3.2",
+ "axobject-query": "^4.1.0",
+ "boxen": "8.0.1",
+ "ci-info": "^4.3.1",
+ "clsx": "^2.1.1",
+ "common-ancestor-path": "^1.0.1",
+ "cookie": "^1.1.1",
+ "cssesc": "^3.0.0",
+ "debug": "^4.4.3",
+ "deterministic-object-hash": "^2.0.2",
+ "devalue": "^5.6.2",
+ "diff": "^8.0.3",
+ "dlv": "^1.1.3",
+ "dset": "^3.1.4",
+ "es-module-lexer": "^1.7.0",
+ "esbuild": "^0.27.3",
+ "estree-walker": "^3.0.3",
+ "flattie": "^1.1.1",
+ "fontace": "~0.4.0",
+ "github-slugger": "^2.0.0",
+ "html-escaper": "3.0.3",
+ "http-cache-semantics": "^4.2.0",
+ "import-meta-resolve": "^4.2.0",
+ "js-yaml": "^4.1.1",
+ "magic-string": "^0.30.21",
+ "magicast": "^0.5.1",
+ "mrmime": "^2.0.1",
+ "neotraverse": "^0.6.18",
+ "p-limit": "^6.2.0",
+ "p-queue": "^8.1.1",
+ "package-manager-detector": "^1.6.0",
+ "piccolore": "^0.1.3",
+ "picomatch": "^4.0.3",
+ "prompts": "^2.4.2",
+ "rehype": "^13.0.2",
+ "semver": "^7.7.3",
+ "shiki": "^3.21.0",
+ "smol-toml": "^1.6.0",
+ "svgo": "^4.0.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tsconfck": "^3.1.6",
+ "ultrahtml": "^1.6.0",
+ "unifont": "~0.7.3",
+ "unist-util-visit": "^5.0.0",
+ "unstorage": "^1.17.4",
+ "vfile": "^6.0.3",
+ "vite": "^6.4.1",
+ "vitefu": "^1.1.1",
+ "xxhash-wasm": "^1.1.0",
+ "yargs-parser": "^21.1.1",
+ "yocto-spinner": "^0.2.3",
+ "zod": "^3.25.76",
+ "zod-to-json-schema": "^3.25.1",
+ "zod-to-ts": "^1.2.0"
+ },
+ "bin": {
+ "astro": "astro.js"
+ },
+ "engines": {
+ "node": "18.20.8 || ^20.3.0 || >=22.0.0",
+ "npm": ">=9.6.5",
+ "pnpm": ">=7.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/astrodotbuild"
+ },
+ "optionalDependencies": {
+ "sharp": "^0.34.0"
+ }
+ },
+ "node_modules/astro-expressive-code": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.7.tgz",
+ "integrity": "sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ==",
+ "license": "MIT",
+ "dependencies": {
+ "rehype-expressive-code": "^0.41.7"
+ },
+ "peerDependencies": {
+ "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/astro/node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/astro/node_modules/zod-to-ts": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz",
+ "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==",
+ "peerDependencies": {
+ "typescript": "^4.9.4 || ^5.0.2",
+ "zod": "^3"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/base-64": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
+ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
+ "license": "MIT"
+ },
+ "node_modules/bcp-47": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz",
+ "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/bcp-47-match": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz",
+ "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/blake3-wasm": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
+ "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "license": "MIT"
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/boxen": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz",
+ "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^3.0.1",
+ "camelcase": "^8.0.0",
+ "chalk": "^5.3.0",
+ "cli-boxes": "^3.0.0",
+ "string-width": "^7.2.0",
+ "type-fest": "^4.21.0",
+ "widest-line": "^5.0.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
+ "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
+ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
+ "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/collapse-white-space": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
+ "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/common-ancestor-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
+ "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==",
+ "license": "ISC"
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cookie-es": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz",
+ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
+ "license": "MIT"
+ },
+ "node_modules/crossws": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz",
+ "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==",
+ "license": "MIT",
+ "dependencies": {
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-selector-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.3.0.tgz",
+ "integrity": "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decode-named-character-reference": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
+ "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
+ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/deterministic-object-hash": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz",
+ "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "base-64": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/devalue": {
+ "version": "5.6.4",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz",
+ "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==",
+ "license": "MIT"
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/diff": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
+ "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/direction": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz",
+ "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==",
+ "license": "MIT",
+ "bin": {
+ "direction": "cli.js"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "license": "MIT"
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/dom-serializer/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dset": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
+ "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/emmet": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.11.tgz",
+ "integrity": "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==",
+ "dev": true,
+ "license": "MIT",
+ "workspaces": [
+ "./packages/scanner",
+ "./packages/abbreviation",
+ "./packages/css-abbreviation",
+ "./"
+ ],
+ "dependencies": {
+ "@emmetio/abbreviation": "^2.3.3",
+ "@emmetio/css-abbreviation": "^2.1.8"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
+ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/error-stack-parser-es": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz",
+ "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "license": "MIT"
+ },
+ "node_modules/esast-util-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
+ "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/esast-util-from-js": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz",
+ "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "acorn": "^8.0.0",
+ "esast-util-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
+ "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.4",
+ "@esbuild/android-arm": "0.27.4",
+ "@esbuild/android-arm64": "0.27.4",
+ "@esbuild/android-x64": "0.27.4",
+ "@esbuild/darwin-arm64": "0.27.4",
+ "@esbuild/darwin-x64": "0.27.4",
+ "@esbuild/freebsd-arm64": "0.27.4",
+ "@esbuild/freebsd-x64": "0.27.4",
+ "@esbuild/linux-arm": "0.27.4",
+ "@esbuild/linux-arm64": "0.27.4",
+ "@esbuild/linux-ia32": "0.27.4",
+ "@esbuild/linux-loong64": "0.27.4",
+ "@esbuild/linux-mips64el": "0.27.4",
+ "@esbuild/linux-ppc64": "0.27.4",
+ "@esbuild/linux-riscv64": "0.27.4",
+ "@esbuild/linux-s390x": "0.27.4",
+ "@esbuild/linux-x64": "0.27.4",
+ "@esbuild/netbsd-arm64": "0.27.4",
+ "@esbuild/netbsd-x64": "0.27.4",
+ "@esbuild/openbsd-arm64": "0.27.4",
+ "@esbuild/openbsd-x64": "0.27.4",
+ "@esbuild/openharmony-arm64": "0.27.4",
+ "@esbuild/sunos-x64": "0.27.4",
+ "@esbuild/win32-arm64": "0.27.4",
+ "@esbuild/win32-ia32": "0.27.4",
+ "@esbuild/win32-x64": "0.27.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/estree-util-attach-comments": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz",
+ "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-build-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz",
+ "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "estree-walker": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-is-identifier-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+ "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-scope": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz",
+ "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-to-js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz",
+ "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "astring": "^1.8.0",
+ "source-map": "^0.7.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-visit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz",
+ "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
+ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
+ "license": "MIT"
+ },
+ "node_modules/expressive-code": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.7.tgz",
+ "integrity": "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expressive-code/core": "^0.41.7",
+ "@expressive-code/plugin-frames": "^0.41.7",
+ "@expressive-code/plugin-shiki": "^0.41.7",
+ "@expressive-code/plugin-text-markers": "^0.41.7"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
+ "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/flattie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz",
+ "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fontace": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz",
+ "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==",
+ "license": "MIT",
+ "dependencies": {
+ "fontkitten": "^1.0.2"
+ }
+ },
+ "node_modules/fontkitten": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz",
+ "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==",
+ "license": "MIT",
+ "dependencies": {
+ "tiny-inflate": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
+ "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/github-slugger": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
+ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
+ "license": "ISC"
+ },
+ "node_modules/h3": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.9.tgz",
+ "integrity": "sha512-H7UPnyIupUOYUQu7f2x7ABVeMyF/IbJjqn20WSXpMdnQB260luADUkSgJU7QTWLutq8h3tUayMQ1DdbSYX5LkA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie-es": "^1.2.2",
+ "crossws": "^0.3.5",
+ "defu": "^6.1.4",
+ "destr": "^2.0.5",
+ "iron-webcrypto": "^1.2.1",
+ "node-mock-http": "^1.0.4",
+ "radix3": "^1.1.2",
+ "ufo": "^1.6.3",
+ "uncrypto": "^0.1.3"
+ }
+ },
+ "node_modules/hast-util-embedded": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz",
+ "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-is-element": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-format": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz",
+ "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-minify-whitespace": "^1.0.0",
+ "hast-util-phrasing": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-whitespace-sensitive-tag-names": "^3.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-html": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
+ "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "devlop": "^1.1.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "parse5": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-from-parse5": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
+ "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "hastscript": "^9.0.0",
+ "property-information": "^7.0.0",
+ "vfile": "^6.0.0",
+ "vfile-location": "^5.0.0",
+ "web-namespaces": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-has-property": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz",
+ "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-body-ok-link": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz",
+ "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-element": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz",
+ "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-minify-whitespace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz",
+ "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-is-element": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-phrasing": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz",
+ "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-embedded": "^3.0.0",
+ "hast-util-has-property": "^3.0.0",
+ "hast-util-is-body-ok-link": "^3.0.0",
+ "hast-util-is-element": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-raw": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz",
+ "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "hast-util-from-parse5": "^8.0.0",
+ "hast-util-to-parse5": "^8.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "parse5": "^7.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-select": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz",
+ "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "bcp-47-match": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "css-selector-parser": "^3.0.0",
+ "devlop": "^1.0.0",
+ "direction": "^2.0.0",
+ "hast-util-has-property": "^3.0.0",
+ "hast-util-to-string": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "nth-check": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-estree": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz",
+ "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-attach-comments": "^3.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-jsx-runtime": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+ "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-parse5": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz",
+ "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "web-namespaces": "^2.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-string": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz",
+ "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-to-text": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz",
+ "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "hast-util-is-element": "^3.0.0",
+ "unist-util-find-after": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
+ "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==",
+ "license": "MIT"
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/html-whitespace-sensitive-tag-names": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz",
+ "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
+ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/i18next": {
+ "version": "23.16.8",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
+ "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
+ "node_modules/import-meta-resolve": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
+ "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
+ "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==",
+ "license": "MIT"
+ },
+ "node_modules/iron-webcrypto": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz",
+ "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/brc-dd"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
+ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
+ "license": "MIT"
+ },
+ "node_modules/is-decimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
+ "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-inside-container": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsonc-parser": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz",
+ "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/klona": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
+ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/longest-streak": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "11.2.7",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
+ "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz",
+ "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/markdown-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz",
+ "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdown-table": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+ "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/mdast-util-definitions": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz",
+ "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-directive": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz",
+ "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-find-and-replace": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+ "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "escape-string-regexp": "^5.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-from-markdown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
+ "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark": "^4.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+ "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-gfm-autolink-literal": "^2.0.0",
+ "mdast-util-gfm-footnote": "^2.0.0",
+ "mdast-util-gfm-strikethrough": "^2.0.0",
+ "mdast-util-gfm-table": "^2.0.0",
+ "mdast-util-gfm-task-list-item": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-autolink-literal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+ "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-find-and-replace": "^3.0.0",
+ "micromark-util-character": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-strikethrough": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+ "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+ "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "markdown-table": "^3.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-gfm-task-list-item": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+ "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
+ "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-expression": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+ "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-jsx": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+ "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdxjs-esm": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+ "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-phrasing": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+ "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+ "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^4.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+ "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "license": "CC0-1.0"
+ },
+ "node_modules/micromark": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+ "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+ "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-destination": "^2.0.0",
+ "micromark-factory-label": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-title": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-html-tag-name": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-extension-directive": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz",
+ "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "parse-entities": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+ "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-extension-gfm-autolink-literal": "^2.0.0",
+ "micromark-extension-gfm-footnote": "^2.0.0",
+ "micromark-extension-gfm-strikethrough": "^2.0.0",
+ "micromark-extension-gfm-table": "^2.0.0",
+ "micromark-extension-gfm-tagfilter": "^2.0.0",
+ "micromark-extension-gfm-task-list-item": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-autolink-literal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+ "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-footnote": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+ "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-strikethrough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+ "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-table": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+ "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-tagfilter": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+ "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-gfm-task-list-item": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+ "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-expression": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
+ "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-extension-mdx-jsx": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz",
+ "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "micromark-factory-mdx-expression": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-md": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz",
+ "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz",
+ "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.0.0",
+ "acorn-jsx": "^5.0.0",
+ "micromark-extension-mdx-expression": "^3.0.0",
+ "micromark-extension-mdx-jsx": "^3.0.0",
+ "micromark-extension-mdx-md": "^2.0.0",
+ "micromark-extension-mdxjs-esm": "^3.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs-esm": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz",
+ "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-factory-destination": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+ "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-label": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+ "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-mdx-expression": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz",
+ "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-events-to-acorn": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-position-from-estree": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ }
+ },
+ "node_modules/micromark-factory-space": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+ "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-title": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+ "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-whitespace": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+ "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.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",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-chunked": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+ "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-classify-character": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+ "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+ "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+ "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-string": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+ "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-events-to-acorn": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz",
+ "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/unist": "^3.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-visit": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "vfile-message": "^4.0.0"
+ }
+ },
+ "node_modules/micromark-util-html-tag-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+ "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-normalize-identifier": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+ "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-resolve-all": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+ "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-subtokenize": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+ "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/miniflare": {
+ "version": "4.20260317.2",
+ "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260317.2.tgz",
+ "integrity": "sha512-qNL+yWAFMX6fr0pWU6Lx1vNpPobpnDSF1V8eunIckWvoIQl8y1oBjL2RJFEGY3un+l3f9gwW9dirDPP26usYJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "0.8.1",
+ "sharp": "^0.34.5",
+ "undici": "7.24.4",
+ "workerd": "1.20260317.1",
+ "ws": "8.18.0",
+ "youch": "4.1.0-beta.10"
+ },
+ "bin": {
+ "miniflare": "bootstrap.js"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-darwin-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linux-arm": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linux-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linux-s390x": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linux-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-wasm32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.7.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-win32-ia32": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/@img/sharp-win32-x64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/miniflare/node_modules/sharp": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@img/colour": "^1.0.0",
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/muggle-string": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
+ "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/neotraverse": {
+ "version": "0.6.18",
+ "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz",
+ "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/nlcst-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz",
+ "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/node-fetch-native": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
+ "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
+ "license": "MIT"
+ },
+ "node_modules/node-mock-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz",
+ "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/ofetch": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz",
+ "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==",
+ "license": "MIT",
+ "dependencies": {
+ "destr": "^2.0.5",
+ "node-fetch-native": "^1.6.7",
+ "ufo": "^1.6.1"
+ }
+ },
+ "node_modules/ohash": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
+ "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-parser": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz",
+ "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==",
+ "license": "MIT"
+ },
+ "node_modules/oniguruma-to-es": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz",
+ "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==",
+ "license": "MIT",
+ "dependencies": {
+ "oniguruma-parser": "^0.12.1",
+ "regex": "^6.1.0",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz",
+ "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==",
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-queue": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz",
+ "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^5.0.1",
+ "p-timeout": "^6.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz",
+ "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/pagefind": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz",
+ "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==",
+ "license": "MIT",
+ "bin": {
+ "pagefind": "lib/runner/bin.cjs"
+ },
+ "optionalDependencies": {
+ "@pagefind/darwin-arm64": "1.4.0",
+ "@pagefind/darwin-x64": "1.4.0",
+ "@pagefind/freebsd-x64": "1.4.0",
+ "@pagefind/linux-arm64": "1.4.0",
+ "@pagefind/linux-x64": "1.4.0",
+ "@pagefind/windows-x64": "1.4.0"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+ "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "character-entities-legacy": "^3.0.0",
+ "character-reference-invalid": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0",
+ "is-hexadecimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-entities/node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
+ "node_modules/parse-latin": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz",
+ "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "@types/unist": "^3.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unist-util-modify-children": "^4.0.0",
+ "unist-util-visit-children": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
+ "license": "MIT"
+ },
+ "node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "license": "MIT"
+ },
+ "node_modules/piccolore": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz",
+ "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==",
+ "license": "ISC"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
+ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+ "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/radix3": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
+ "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
+ "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/recma-build-jsx": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz",
+ "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-util-build-jsx": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-jsx": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz",
+ "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn-jsx": "^5.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "recma-parse": "^1.0.0",
+ "recma-stringify": "^1.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/recma-parse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz",
+ "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "esast-util-from-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/recma-stringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz",
+ "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-util-to-js": "^2.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz",
+ "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "license": "MIT"
+ },
+ "node_modules/rehype": {
+ "version": "13.0.2",
+ "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz",
+ "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "rehype-parse": "^9.0.0",
+ "rehype-stringify": "^10.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-expressive-code": {
+ "version": "0.41.7",
+ "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.7.tgz",
+ "integrity": "sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "expressive-code": "^0.41.7"
+ }
+ },
+ "node_modules/rehype-format": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz",
+ "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-format": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-parse": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
+ "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-from-html": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-raw": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
+ "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-raw": "^9.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-recma": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz",
+ "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "hast-util-to-estree": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rehype-stringify": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz",
+ "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "hast-util-to-html": "^9.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-directive": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz",
+ "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-directive": "^3.0.0",
+ "micromark-extension-directive": "^3.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-gfm": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-gfm": "^3.0.0",
+ "micromark-extension-gfm": "^3.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-stringify": "^11.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz",
+ "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==",
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-mdx": "^3.0.0",
+ "micromark-extension-mdxjs": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+ "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+ "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-smartypants": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz",
+ "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==",
+ "license": "MIT",
+ "dependencies": {
+ "retext": "^9.0.0",
+ "retext-smartypants": "^6.0.0",
+ "unified": "^11.0.4",
+ "unist-util-visit": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/remark-stringify": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
+ "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/request-light": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.7.0.tgz",
+ "integrity": "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/retext": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz",
+ "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "retext-latin": "^4.0.0",
+ "retext-stringify": "^4.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-latin": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz",
+ "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "parse-latin": "^7.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-smartypants": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz",
+ "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/retext-stringify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz",
+ "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/nlcst": "^2.0.0",
+ "nlcst-to-string": "^4.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.59.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+ "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.59.0",
+ "@rollup/rollup-android-arm64": "4.59.0",
+ "@rollup/rollup-darwin-arm64": "4.59.0",
+ "@rollup/rollup-darwin-x64": "4.59.0",
+ "@rollup/rollup-freebsd-arm64": "4.59.0",
+ "@rollup/rollup-freebsd-x64": "4.59.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+ "@rollup/rollup-linux-arm64-musl": "4.59.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+ "@rollup/rollup-linux-loong64-musl": "4.59.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+ "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-gnu": "4.59.0",
+ "@rollup/rollup-linux-x64-musl": "4.59.0",
+ "@rollup/rollup-openbsd-x64": "4.59.0",
+ "@rollup/rollup-openharmony-arm64": "4.59.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+ "@rollup/rollup-win32-x64-gnu": "4.59.0",
+ "@rollup/rollup-win32-x64-msvc": "4.59.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
+ "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/sharp": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
+ "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.3",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.33.5",
+ "@img/sharp-darwin-x64": "0.33.5",
+ "@img/sharp-libvips-darwin-arm64": "1.0.4",
+ "@img/sharp-libvips-darwin-x64": "1.0.4",
+ "@img/sharp-libvips-linux-arm": "1.0.5",
+ "@img/sharp-libvips-linux-arm64": "1.0.4",
+ "@img/sharp-libvips-linux-s390x": "1.0.4",
+ "@img/sharp-libvips-linux-x64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
+ "@img/sharp-linux-arm": "0.33.5",
+ "@img/sharp-linux-arm64": "0.33.5",
+ "@img/sharp-linux-s390x": "0.33.5",
+ "@img/sharp-linux-x64": "0.33.5",
+ "@img/sharp-linuxmusl-arm64": "0.33.5",
+ "@img/sharp-linuxmusl-x64": "0.33.5",
+ "@img/sharp-wasm32": "0.33.5",
+ "@img/sharp-win32-ia32": "0.33.5",
+ "@img/sharp-win32-x64": "0.33.5"
+ }
+ },
+ "node_modules/shiki": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz",
+ "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "3.23.0",
+ "@shikijs/engine-javascript": "3.23.0",
+ "@shikijs/engine-oniguruma": "3.23.0",
+ "@shikijs/langs": "3.23.0",
+ "@shikijs/themes": "3.23.0",
+ "@shikijs/types": "3.23.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
+ "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "license": "MIT"
+ },
+ "node_modules/sitemap": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz",
+ "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "^24.9.2",
+ "@types/sax": "^1.2.1",
+ "arg": "^5.0.0",
+ "sax": "^1.4.1"
+ },
+ "bin": {
+ "sitemap": "dist/esm/cli.js"
+ },
+ "engines": {
+ "node": ">=20.19.5",
+ "npm": ">=10.8.2"
+ }
+ },
+ "node_modules/smol-toml": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
+ "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/cyyynthia"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
+ "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/stream-replace-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
+ "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==",
+ "license": "MIT"
+ },
+ "node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/style-to-js": {
+ "version": "1.1.21",
+ "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
+ "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "style-to-object": "1.0.14"
+ }
+ },
+ "node_modules/style-to-object": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
+ "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
+ "license": "MIT",
+ "dependencies": {
+ "inline-style-parser": "0.2.7"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz",
+ "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/svgo": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz",
+ "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "css-select": "^5.1.0",
+ "css-tree": "^3.0.1",
+ "css-what": "^6.1.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.1.1",
+ "sax": "^1.5.0"
+ },
+ "bin": {
+ "svgo": "bin/svgo.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz",
+ "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/tsconfck": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz",
+ "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==",
+ "license": "MIT",
+ "bin": {
+ "tsconfck": "bin/tsconfck.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typesafe-path": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz",
+ "integrity": "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-auto-import-cache": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.6.tgz",
+ "integrity": "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.8"
+ }
+ },
+ "node_modules/ufo": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz",
+ "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==",
+ "license": "MIT"
+ },
+ "node_modules/ultrahtml": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz",
+ "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==",
+ "license": "MIT"
+ },
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
+ },
+ "node_modules/undici": {
+ "version": "7.24.4",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.4.tgz",
+ "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT"
+ },
+ "node_modules/unenv": {
+ "version": "2.0.0-rc.24",
+ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
+ "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==",
+ "license": "MIT",
+ "dependencies": {
+ "pathe": "^2.0.3"
+ }
+ },
+ "node_modules/unified": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "bail": "^2.0.0",
+ "devlop": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unifont": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz",
+ "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==",
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "^3.1.0",
+ "ofetch": "^1.5.1",
+ "ohash": "^2.0.11"
+ }
+ },
+ "node_modules/unist-util-find-after": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz",
+ "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-modify-children": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz",
+ "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "array-iterate": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position-from-estree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz",
+ "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz",
+ "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-visit": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+ "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-children": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz",
+ "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+ "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unstorage": {
+ "version": "1.17.4",
+ "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz",
+ "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "^3.1.3",
+ "chokidar": "^5.0.0",
+ "destr": "^2.0.5",
+ "h3": "^1.15.5",
+ "lru-cache": "^11.2.0",
+ "node-fetch-native": "^1.6.7",
+ "ofetch": "^1.5.1",
+ "ufo": "^1.6.3"
+ },
+ "peerDependencies": {
+ "@azure/app-configuration": "^1.8.0",
+ "@azure/cosmos": "^4.2.0",
+ "@azure/data-tables": "^13.3.0",
+ "@azure/identity": "^4.6.0",
+ "@azure/keyvault-secrets": "^4.9.0",
+ "@azure/storage-blob": "^12.26.0",
+ "@capacitor/preferences": "^6 || ^7 || ^8",
+ "@deno/kv": ">=0.9.0",
+ "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0",
+ "@planetscale/database": "^1.19.0",
+ "@upstash/redis": "^1.34.3",
+ "@vercel/blob": ">=0.27.1",
+ "@vercel/functions": "^2.2.12 || ^3.0.0",
+ "@vercel/kv": "^1 || ^2 || ^3",
+ "aws4fetch": "^1.0.20",
+ "db0": ">=0.2.1",
+ "idb-keyval": "^6.2.1",
+ "ioredis": "^5.4.2",
+ "uploadthing": "^7.4.4"
+ },
+ "peerDependenciesMeta": {
+ "@azure/app-configuration": {
+ "optional": true
+ },
+ "@azure/cosmos": {
+ "optional": true
+ },
+ "@azure/data-tables": {
+ "optional": true
+ },
+ "@azure/identity": {
+ "optional": true
+ },
+ "@azure/keyvault-secrets": {
+ "optional": true
+ },
+ "@azure/storage-blob": {
+ "optional": true
+ },
+ "@capacitor/preferences": {
+ "optional": true
+ },
+ "@deno/kv": {
+ "optional": true
+ },
+ "@netlify/blobs": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/blob": {
+ "optional": true
+ },
+ "@vercel/functions": {
+ "optional": true
+ },
+ "@vercel/kv": {
+ "optional": true
+ },
+ "aws4fetch": {
+ "optional": true
+ },
+ "db0": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "uploadthing": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-location": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz",
+ "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vite/node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/vitefu": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz",
+ "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==",
+ "license": "MIT",
+ "workspaces": [
+ "tests/deps/*",
+ "tests/projects/*",
+ "tests/projects/workspace/packages/*"
+ ],
+ "peerDependencies": {
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-css": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.70.tgz",
+ "integrity": "sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vscode-css-languageservice": "^6.3.0",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-emmet": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.70.tgz",
+ "integrity": "sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@emmetio/css-parser": "^0.4.1",
+ "@emmetio/html-matcher": "^1.3.0",
+ "@vscode/emmet-helper": "^2.9.3",
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-html": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.70.tgz",
+ "integrity": "sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vscode-html-languageservice": "^5.3.0",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-prettier": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.70.tgz",
+ "integrity": "sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0",
+ "prettier": "^2.2 || ^3.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ },
+ "prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-typescript": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.70.tgz",
+ "integrity": "sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-browserify": "^1.0.1",
+ "semver": "^7.6.2",
+ "typescript-auto-import-cache": "^0.3.5",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-nls": "^5.2.0",
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-typescript-twoslash-queries": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.70.tgz",
+ "integrity": "sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vscode-uri": "^3.0.8"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/volar-service-yaml": {
+ "version": "0.0.70",
+ "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.70.tgz",
+ "integrity": "sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vscode-uri": "^3.0.8",
+ "yaml-language-server": "~1.20.0"
+ },
+ "peerDependencies": {
+ "@volar/language-service": "~2.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@volar/language-service": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vscode-css-languageservice": {
+ "version": "6.3.10",
+ "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.10.tgz",
+ "integrity": "sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vscode/l10n": "^0.0.18",
+ "vscode-languageserver-textdocument": "^1.0.12",
+ "vscode-languageserver-types": "3.17.5",
+ "vscode-uri": "^3.1.0"
+ }
+ },
+ "node_modules/vscode-html-languageservice": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.6.2.tgz",
+ "integrity": "sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vscode/l10n": "^0.0.18",
+ "vscode-languageserver-textdocument": "^1.0.12",
+ "vscode-languageserver-types": "^3.17.5",
+ "vscode-uri": "^3.1.0"
+ }
+ },
+ "node_modules/vscode-json-languageservice": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz",
+ "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsonc-parser": "^3.0.0",
+ "vscode-languageserver-textdocument": "^1.0.1",
+ "vscode-languageserver-types": "^3.16.0",
+ "vscode-nls": "^5.0.0",
+ "vscode-uri": "^3.0.2"
+ },
+ "engines": {
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/vscode-json-languageservice/node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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",
+ "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",
+ "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",
+ "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"
+ },
+ "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"
+ },
+ "node_modules/vscode-nls": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz",
+ "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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"
+ },
+ "node_modules/web-namespaces": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
+ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/which-pm-runs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz",
+ "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz",
+ "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==",
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/workerd": {
+ "version": "1.20260317.1",
+ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260317.1.tgz",
+ "integrity": "sha512-ZuEq1OdrJBS+NV+L5HMYPCzVn49a2O60slQiiLpG44jqtlOo+S167fWC76kEXteXLLLydeuRrluRel7WdOUa4g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "workerd": "bin/workerd"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "@cloudflare/workerd-darwin-64": "1.20260317.1",
+ "@cloudflare/workerd-darwin-arm64": "1.20260317.1",
+ "@cloudflare/workerd-linux-64": "1.20260317.1",
+ "@cloudflare/workerd-linux-arm64": "1.20260317.1",
+ "@cloudflare/workerd-windows-64": "1.20260317.1"
+ }
+ },
+ "node_modules/wrangler": {
+ "version": "4.77.0",
+ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.77.0.tgz",
+ "integrity": "sha512-E2Gm69+K++BFd3QvoWjC290RPQj1vDOUotA++sNHmtKPb7EP6C8Qv+1D5Ii73tfZtyNgakpqHlh8lBBbVWTKAQ==",
+ "dev": true,
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "@cloudflare/kv-asset-handler": "0.4.2",
+ "@cloudflare/unenv-preset": "2.16.0",
+ "blake3-wasm": "2.1.5",
+ "esbuild": "0.27.3",
+ "miniflare": "4.20260317.2",
+ "path-to-regexp": "6.3.0",
+ "unenv": "2.0.0-rc.24",
+ "workerd": "1.20260317.1"
+ },
+ "bin": {
+ "wrangler": "bin/wrangler.js",
+ "wrangler2": "bin/wrangler.js"
+ },
+ "engines": {
+ "node": ">=20.3.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@cloudflare/workers-types": "^4.20260317.1"
+ },
+ "peerDependenciesMeta": {
+ "@cloudflare/workers-types": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz",
+ "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz",
+ "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz",
+ "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/android-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz",
+ "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz",
+ "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz",
+ "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz",
+ "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-arm": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz",
+ "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz",
+ "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz",
+ "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz",
+ "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz",
+ "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz",
+ "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz",
+ "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz",
+ "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/linux-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz",
+ "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz",
+ "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz",
+ "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz",
+ "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz",
+ "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz",
+ "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz",
+ "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/@esbuild/win32-x64": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz",
+ "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrangler/node_modules/esbuild": {
+ "version": "0.27.3",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
+ "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.3",
+ "@esbuild/android-arm": "0.27.3",
+ "@esbuild/android-arm64": "0.27.3",
+ "@esbuild/android-x64": "0.27.3",
+ "@esbuild/darwin-arm64": "0.27.3",
+ "@esbuild/darwin-x64": "0.27.3",
+ "@esbuild/freebsd-arm64": "0.27.3",
+ "@esbuild/freebsd-x64": "0.27.3",
+ "@esbuild/linux-arm": "0.27.3",
+ "@esbuild/linux-arm64": "0.27.3",
+ "@esbuild/linux-ia32": "0.27.3",
+ "@esbuild/linux-loong64": "0.27.3",
+ "@esbuild/linux-mips64el": "0.27.3",
+ "@esbuild/linux-ppc64": "0.27.3",
+ "@esbuild/linux-riscv64": "0.27.3",
+ "@esbuild/linux-s390x": "0.27.3",
+ "@esbuild/linux-x64": "0.27.3",
+ "@esbuild/netbsd-arm64": "0.27.3",
+ "@esbuild/netbsd-x64": "0.27.3",
+ "@esbuild/openbsd-arm64": "0.27.3",
+ "@esbuild/openbsd-x64": "0.27.3",
+ "@esbuild/openharmony-arm64": "0.27.3",
+ "@esbuild/sunos-x64": "0.27.3",
+ "@esbuild/win32-arm64": "0.27.3",
+ "@esbuild/win32-ia32": "0.27.3",
+ "@esbuild/win32-x64": "0.27.3"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xxhash-wasm": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
+ "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==",
+ "license": "MIT"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
+ "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
+ "devOptional": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yaml-language-server": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.20.0.tgz",
+ "integrity": "sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vscode/l10n": "^0.0.18",
+ "ajv": "^8.17.1",
+ "ajv-draft-04": "^1.0.0",
+ "prettier": "^3.5.0",
+ "request-light": "^0.5.7",
+ "vscode-json-languageservice": "4.1.8",
+ "vscode-languageserver": "^9.0.0",
+ "vscode-languageserver-textdocument": "^1.0.1",
+ "vscode-languageserver-types": "^3.16.0",
+ "vscode-uri": "^3.0.2",
+ "yaml": "2.7.1"
+ },
+ "bin": {
+ "yaml-language-server": "bin/yaml-language-server"
+ }
+ },
+ "node_modules/yaml-language-server/node_modules/request-light": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz",
+ "integrity": "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/yaml-language-server/node_modules/yaml": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
+ "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
+ "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yocto-spinner": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz",
+ "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "yoctocolors": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=18.19"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
+ "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/youch": {
+ "version": "4.1.0-beta.10",
+ "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz",
+ "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/colors": "^4.1.5",
+ "@poppinss/dumper": "^0.6.4",
+ "@speed-highlight/core": "^1.2.7",
+ "cookie": "^1.0.2",
+ "youch-core": "^0.3.3"
+ }
+ },
+ "node_modules/youch-core": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz",
+ "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@poppinss/exception": "^1.2.2",
+ "error-stack-parser-es": "^1.0.5"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-to-json-schema": {
+ "version": "3.25.1",
+ "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
+ "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "zod": "^3.25 || ^4"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/apps/docs-site/package.json b/apps/docs-site/package.json
new file mode 100644
index 00000000..0d8c766d
--- /dev/null
+++ b/apps/docs-site/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "@dtax/docs-site",
+ "version": "0.0.1",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "astro dev",
+ "build": "astro build",
+ "typecheck": "astro check",
+ "preview": "npm run build && wrangler dev",
+ "deploy": "npm run build && wrangler deploy",
+ "cf-typegen": "wrangler types"
+ },
+ "dependencies": {
+ "@astrojs/cloudflare": "12",
+ "@astrojs/starlight": "^0.33.0",
+ "astro": "^5.0.0",
+ "sharp": "^0.33.5",
+ "typescript": "^5.9.3",
+ "zod": "^3.25.76"
+ },
+ "devDependencies": {
+ "@astrojs/check": "^0.9.8",
+ "wrangler": "^4.77.0"
+ }
+}
diff --git a/apps/docs-site/public/.assetsignore b/apps/docs-site/public/.assetsignore
new file mode 100644
index 00000000..1b006a0f
--- /dev/null
+++ b/apps/docs-site/public/.assetsignore
@@ -0,0 +1,2 @@
+_worker.js
+_routes.json
\ No newline at end of file
diff --git a/apps/docs-site/public/_redirects b/apps/docs-site/public/_redirects
new file mode 100644
index 00000000..76781fc1
--- /dev/null
+++ b/apps/docs-site/public/_redirects
@@ -0,0 +1 @@
+/ /en/ 302
diff --git a/apps/docs-site/src/assets/hero.png b/apps/docs-site/src/assets/hero.png
new file mode 100644
index 00000000..472ea2e2
Binary files /dev/null and b/apps/docs-site/src/assets/hero.png differ
diff --git a/apps/docs-site/src/assets/logo-dark.svg b/apps/docs-site/src/assets/logo-dark.svg
new file mode 100644
index 00000000..86b210c0
--- /dev/null
+++ b/apps/docs-site/src/assets/logo-dark.svg
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/docs-site/src/assets/logo-light.svg b/apps/docs-site/src/assets/logo-light.svg
new file mode 100644
index 00000000..728a4aa1
--- /dev/null
+++ b/apps/docs-site/src/assets/logo-light.svg
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/docs-site/src/assets/logo.png b/apps/docs-site/src/assets/logo.png
new file mode 100644
index 00000000..1706ff58
Binary files /dev/null and b/apps/docs-site/src/assets/logo.png differ
diff --git a/apps/docs-site/src/components/Footer.astro b/apps/docs-site/src/components/Footer.astro
new file mode 100644
index 00000000..ab052183
--- /dev/null
+++ b/apps/docs-site/src/components/Footer.astro
@@ -0,0 +1,142 @@
+---
+const year = new Date().getFullYear();
+---
+
+
+
+
diff --git a/apps/docs-site/src/content.config.ts b/apps/docs-site/src/content.config.ts
new file mode 100644
index 00000000..7fbcf2c3
--- /dev/null
+++ b/apps/docs-site/src/content.config.ts
@@ -0,0 +1,7 @@
+import { defineCollection } from "astro:content";
+import { docsLoader } from "@astrojs/starlight/loaders";
+import { docsSchema } from "@astrojs/starlight/schema";
+
+export const collections = {
+ docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
+};
diff --git a/apps/docs-site/src/content/docs/de/api/authentication.mdx b/apps/docs-site/src/content/docs/de/api/authentication.mdx
new file mode 100644
index 00000000..00807b91
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/api/authentication.mdx
@@ -0,0 +1,44 @@
+---
+title: Authentifizierung
+description: So authentifizieren Sie sich bei der dTax REST API
+draft: false
+---
+
+Die dTax API verwendet **HttpOnly-Session-Cookies** zur Authentifizierung. Dies verhindert XSS-Token-Diebstahl.
+
+## Registrierung / Anmeldung
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+```
+
+Die Antwort setzt ein `session`-HttpOnly-Cookie, das 7 Tage gültig ist.
+
+## Cookie verwenden
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions \
+ -b cookies.txt
+```
+
+## OAuth
+
+Google und GitHub OAuth werden ebenfalls unterstützt:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+Beide leiten bei Erfolg zu `getdtax.com/auth/callback` weiter.
diff --git a/apps/docs-site/src/content/docs/de/api/overview.mdx b/apps/docs-site/src/content/docs/de/api/overview.mdx
new file mode 100644
index 00000000..ef7b2b2b
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/api/overview.mdx
@@ -0,0 +1,48 @@
+---
+title: REST API Übersicht
+description: dTax verwaltete REST API — Transaktionen importieren, Gewinne berechnen, Berichte herunterladen
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+Die dTax REST API ist ein verwalteter Dienst unter **`https://getdtax.com/api/v1`**. Sie übernimmt Speicherung, Berechnung und Berichtserstellung, sodass Sie keinen eigenen Zustand verwalten müssen.
+
+## Basis-URL
+
+```
+https://getdtax.com/api/v1
+```
+
+## Authentifizierung
+
+Alle Endpunkte erfordern ein Session-Cookie, das über `/auth/login` erhalten wird. Weitere Details finden Sie unter [Authentifizierung](/de/api/authentication).
+
+## Wichtige Endpunkte
+
+| Endpunkt | Beschreibung |
+|----------|--------------|
+| `POST /transactions/import` | CSV hochladen, automatisch parsen, deduplizieren und speichern |
+| `GET /transactions` | Benutzertransaktionen mit Filtern auflisten |
+| `GET /tax/summary` | Kursgewinn-Zusammenfassung für ein Steuerjahr |
+| `POST /tax/calculate` | Vollständige Gewinnberechnung ausführen |
+| `GET /tax/reports/:id/download` | Formular 8949 / TXF / PDF herunterladen |
+| `GET /notifications` | Benachrichtigungs-Feed des Benutzers |
+
+## OpenAPI-Spezifikation
+
+Die vollständige OpenAPI 3.1-Spezifikation ist verfügbar:
+
+
+
+## Ratenlimits
+
+| Plan | Limit |
+|------|-------|
+| FREE | 50 Transaktionen, 5 KI-Nachrichten/Tag |
+| PRO ($49/Monat) | Unbegrenzt |
+| CPA ($499/Jahr) | Unbegrenzt + 10 Kundenkonten |
diff --git a/apps/docs-site/src/content/docs/de/index.mdx b/apps/docs-site/src/content/docs/de/index.mdx
new file mode 100644
index 00000000..3a6e0aea
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/index.mdx
@@ -0,0 +1,35 @@
+---
+title: dTax Developer Hub
+description: Open-Source-Krypto-Steuer-Engine — 23 Börsen-Parser, 8 Kostenbasis-Methoden, Formular 8949 / TXF-Export.
+template: splash
+hero:
+ tagline: Professionelle Krypto-Steuerberechnungen als npm-Paket.
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: Loslegen
+ link: /de/introduction/
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ TypeScript-Bibliothek ohne Abhängigkeiten. CSVs parsen, Kursgewinne berechnen, Formular 8949 / TXF exportieren.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit und 15 weitere.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+ Kostenlos für Open-Source-Nutzung. Kommerzielle Lizenz für SaaS-Produkte verfügbar.
+
+
diff --git a/apps/docs-site/src/content/docs/de/introduction.mdx b/apps/docs-site/src/content/docs/de/introduction.mdx
new file mode 100644
index 00000000..4d8a9571
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: Einführung
+description: Was ist dTax und der dtax.dev Developer Hub
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# dTax Developer Hub
+
+**dTax** ist eine Open-Core-Krypto-Steuerplattform. Die Kernberechnungs-Engine ist unter AGPL-3.0 lizenziert und als npm-Paket verfügbar — so können Sie professionelle Krypto-Steuerberechnungen in Ihre eigenen Anwendungen integrieren.
+
+## Was Sie hier finden
+
+
+
+ Eine TypeScript-Bibliothek ohne Abhängigkeiten zum Parsen von Börsen-CSVs und zur Berechnung von Kursgewinnen mit jeder Kostenbasis-Methode.
+
+
+ Eine verwaltete API zum Importieren von Transaktionen, Durchführen von Steuerberechnungen und Generieren von Formular 8949 / TXF-Berichten — keine Infrastruktur erforderlich.
+
+
+ Integrierte Parser für Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit und 15 weitere.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+
+## Open-Core-Modell
+
+| Schicht | Lizenz | Zugang |
+|---------|--------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | Öffentlich auf GitHub + npm |
+| REST API | Kommerziell | getdtax.com |
+| Web App | Kommerziell | getdtax.com |
+
+Wenn Sie die Steuer-Engine in einem kommerziellen Produkt verwenden, müssen Sie Ihre Änderungen open-sourcen (AGPL-3.0) **oder** uns für eine kommerzielle Lizenz kontaktieren.
diff --git a/apps/docs-site/src/content/docs/de/quickstart.mdx b/apps/docs-site/src/content/docs/de/quickstart.mdx
new file mode 100644
index 00000000..ee650181
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: Schnellstart
+description: Installieren Sie @dtax/tax-engine und berechnen Sie in 5 Minuten Ihren ersten Kursgewinn
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## Installation
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## CSV parsen und Gewinne berechnen
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## Format automatisch erkennen
+
+Wenn Sie nicht wissen, von welcher Börse die CSV stammt, lassen Sie die Option `format` weg:
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`); // e.g. "coinbase"
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Formular 8949 generieren
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/de/resources/csv-format.mdx b/apps/docs-site/src/content/docs/de/resources/csv-format.mdx
new file mode 100644
index 00000000..56c00f8e
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/resources/csv-format.mdx
@@ -0,0 +1,46 @@
+---
+title: Generisches CSV-Format
+description: So formatieren Sie eine CSV für den Import, wenn Ihre Börse nicht unterstützt wird
+draft: false
+---
+
+import { Steps } from '@astrojs/starlight/components';
+
+Wenn Ihre Börse nicht in der [Parser-Liste](/de/tax-engine/parsers) enthalten ist, können Sie unser generisches CSV-Format verwenden.
+
+## Vorlage herunterladen
+
+[CSV-Vorlage herunterladen](https://getdtax.com/csv-template.csv)
+
+## Spaltenreferenz
+
+| Spalte | Pflichtfeld | Typ | Beispiel |
+|--------|-------------|-----|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | Enum (siehe unten) | `BUY` |
+| `Sent Amount` | — | Dezimalzahl | `0.5` |
+| `Sent Currency` | — | Ticker | `BTC` |
+| `Sent Value USD` | — | Dezimalzahl | `25000.00` |
+| `Received Amount` | — | Dezimalzahl | `10000` |
+| `Received Currency` | — | Ticker | `USDC` |
+| `Received Value USD` | — | Dezimalzahl | `10000.00` |
+| `Fee Amount` | — | Dezimalzahl | `0.001` |
+| `Fee Currency` | — | Ticker | `ETH` |
+| `Fee Value USD` | — | Dezimalzahl | `2.50` |
+| `Notes` | — | Zeichenkette | `Sold on Uniswap` |
+
+## Transaktionstypen
+
+| Typ | Beschreibung |
+|-----|--------------|
+| `BUY` | Krypto mit Fiat kaufen |
+| `SELL` | Krypto gegen Fiat verkaufen |
+| `TRADE` | Krypto-zu-Krypto-Tausch |
+| `TRANSFER_IN` | Empfang von einer anderen Wallet (nicht steuerpflichtig) |
+| `TRANSFER_OUT` | Senden an eine andere Wallet (nicht steuerpflichtig) |
+| `STAKING` | Erhaltene Staking-Belohnungen |
+| `MINING` | Mining-Belohnungen |
+| `AIRDROP` | Erhaltener Airdrop |
+| `INCOME` | Sonstiges Krypto-Einkommen |
+| `FEE` | Eigenständige Gebühr |
+| `UNKNOWN` | Wird automatisch von KI klassifiziert |
diff --git a/apps/docs-site/src/content/docs/de/resources/faq.mdx b/apps/docs-site/src/content/docs/de/resources/faq.mdx
new file mode 100644
index 00000000..58442d19
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: Häufig gestellte Fragen
+description: Häufige Fragen zu dTax-Transaktionssynchronisierung, Wallet-Unterstützung und Steuerberechnungen
+draft: false
+---
+
+## Warum fehlen einige kleine Überweisungen in meiner Transaktionshistorie?
+
+dTax filtert automatisch **Dust-Angriffs-Transaktionen** heraus – Mikroüberweisungen von weniger als 1.000 Wei (0,000001 ETH, ca. $0,003) an Ihre Wallet-Adresse.
+
+### Was ist ein Dust-Angriff?
+
+Ein Dust-Angriff liegt vor, wenn ein böswilliger Akteur eine extrem kleine Menge Kryptowährung (oft nur 1 Wei = 0,000000001 ETH) an Ihre Wallet sendet. Das Ziel ist die De-Anonymisierung von Wallets durch Verfolgung nachfolgender Transaktionen. Diese Überweisungen wurden nicht von Ihnen initiiert und haben keinerlei steuerliche Auswirkungen.
+
+### Warum werden sie gefiltert?
+
+| Grund | Details |
+|-------|---------|
+| **Keine steuerliche Auswirkung** | Beträge unter 1.000 Wei sind weniger als $0,01 wert und stellen keine steuerpflichtigen Ereignisse dar |
+| **Nicht Ihre Transaktionen** | Dust wird *ohne Ihr Einverständnis* an Sie gesendet – Sie haben diese Mittel nie kontrolliert oder bewegt |
+| **Branchenstandard** | CoinTracker, Koinly und andere Krypto-Steuer-Tools filtern Dust-Überweisungen automatisch heraus |
+| **Sauberere Aufzeichnungen** | Das Entfernen von Spam sorgt für eine genaue und prüfbare Transaktionshistorie |
+
+### Was ist der Schwellenwert?
+
+Überweisungen unter **1.000 Wei** (0,000001 ETH) werden für die Transaktionstypen `TRANSFER_IN` und `TRANSFER_OUT` gefiltert. Alle anderen Transaktionstypen (Swaps, Trades, Staking-Rewards usw.) werden unabhängig vom Betrag immer erfasst.
+
+### Beeinflusst das meinen Steuerbericht?
+
+Nein. Das IRS verlangt keine Meldung von Dust-Angriffen – Sie haben diese Vermögenswerte nicht absichtlich erworben, und ihr Wert ist vernachlässigbar. Das Filtern hat keine Auswirkungen auf Ihre Form 8949 oder Kapitalgewinnberechnungen.
+
+---
+
+## Warum zeigt die Preisanreicherung eine Teilanzahl (z. B. „9 / 50")?
+
+Die Preisanreicherungszahl umfasst nur **steuerpflichtige Transaktionen** (BUY, SELL, TRADE, DEX_SWAP, STAKING_REWARD usw.). Einfache Überweisungen zwischen eigenen Wallets (`TRANSFER_IN` / `TRANSFER_OUT`) werden ausgeschlossen, da diese keine steuerpflichtigen Ereignisse sind und für die Steuererklärung keinen USD-Preis benötigen.
+
+---
+
+## Warum dauert die Wallet-Synchronisierung so lange?
+
+Die EVM-Wallet-Synchronisierung fragt bis zu 5 Blockchain-Netzwerke (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism) sequenziell ab, um Ethersscans Free-Tier-Ratenlimit von 5 Anfragen pro Sekunde einzuhalten. Jede Chain führt 5 parallele API-Aufrufe durch. Eine vollständige Synchronisierung aller Chains kann 30–60 Sekunden dauern.
+
+---
+
+## Warum zeigt meine Steuerberechnung $0 für Wallet-Transaktionen?
+
+Wenn Ihre Wallet nur `TRANSFER_IN`- und `TRANSFER_OUT`-Transaktionen enthält, beträgt die Steuersumme $0. Überweisungen zwischen eigenen Wallets sind **keine steuerpflichtigen Ereignisse** – Kapitalgewinne oder -verluste entstehen erst beim Verkauf, Tausch oder Einsatz des Vermögenswerts.
diff --git a/apps/docs-site/src/content/docs/de/resources/license.mdx b/apps/docs-site/src/content/docs/de/resources/license.mdx
new file mode 100644
index 00000000..fd0b5826
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/resources/license.mdx
@@ -0,0 +1,39 @@
+---
+title: Open-Core-Lizenz
+description: AGPL-3.0 Open-Core-Modell — was Sie tun dürfen und müssen
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+Das npm-Paket `@dtax/tax-engine` ist unter der **GNU Affero General Public License v3.0** lizenziert.
+
+### Sie DÜRFEN
+
+- Es kostenlos in persönlichen Projekten verwenden
+- Den Quellcode studieren und modifizieren
+- Modifizierte Versionen verteilen (müssen unter AGPL-3.0 bleiben)
+- Es intern verwenden ohne Open-Sourcing (nur für den internen Gebrauch)
+
+### Sie MÜSSEN (bei Weitergabe)
+
+- Den vollständigen AGPL-3.0-Lizenztext beifügen
+- Alle Modifikationen unter AGPL-3.0 open-sourcen
+- Benutzern Ihres Dienstes Zugang zum Quellcode gewähren
+
+### Sie BENÖTIGEN eine kommerzielle Lizenz, wenn
+
+- Sie ein SaaS-Produkt mit der Engine erstellen, ohne es open-zusourcen
+- Sie Ihre Modifikationen proprietär halten möchten
+
+## Kommerzielle Lizenz
+
+Kontaktieren Sie [hello@getdtax.com](mailto:hello@getdtax.com) für kommerzielle Lizenzierungsoptionen.
+
+## Web App & API
+
+Die dTax-Webanwendung und REST API sind proprietäre Software unter der **dTax Commercial License**. Sie sind nicht Open Source.
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/de/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/de/resources/self-hosting.mdx
new file mode 100644
index 00000000..ed752f14
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/resources/self-hosting.mdx
@@ -0,0 +1,202 @@
+---
+title: Self-Hosting
+description: dTax mit Docker Compose auf dem eigenen Server deployen — vollständiger Stack mit PostgreSQL, Redis, API und Web
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Deploye dTax in unter 15 Minuten auf deinem eigenen Linux-Server mit Docker Compose.
+
+## Voraussetzungen
+
+- Linux-Server (Ubuntu 22.04+ empfohlen), 2+ GB RAM
+- Docker Engine 24+ und Docker Compose v2
+- Ein Domainname, der auf die Server-IP zeigt
+- Ports 80 und 443 in der Firewall geöffnet
+
+## Schnellstart
+
+
+
+1. **Repository klonen**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **Umgebungsvariablen konfigurieren**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ Bearbeite `.env` und setze alle erforderlichen Werte:
+
+ | Variable | Beschreibung |
+ | -------- | ------------ |
+ | `POSTGRES_PASSWORD` | Starkes Datenbankpasswort |
+ | `JWT_SECRET` | Zufallszeichenkette, mindestens 32 Zeichen |
+ | `ENCRYPTION_KEY` | **64-stelliger Hex-String** — siehe Hinweis unten |
+ | `CORS_ORIGIN` | Deine Domain, z.B. `https://tax.example.com` |
+ | `APP_URL` | Gleiche Domain (für Passwort-Reset-E-Mails) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api` (**Build-Zeit-Variable** — muss vor `docker compose build` gesetzt sein) |
+
+
+ Der Verschlüsselungsschlüssel **muss** ein 64-stelliger Hex-String (32 Rohbytes) sein. Andere Formate führen zu einem Absturz beim API-Start.
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **Dienste starten**
+
+ ```bash
+ docker compose up -d
+ ```
+
+ Startet PostgreSQL, Redis, API, Web und nginx. Der `migrate`-Dienst führt Datenbankmigrationen automatisch aus.
+
+ Betrieb überprüfen:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## Architektur
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ Routing │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS mit Let's Encrypt
+
+
+
+1. **nginx-Konfiguration aktualisieren**
+
+ Bearbeite `docker/nginx/nginx.conf` und ersetze `server_name _;` mit deiner Domain:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **Zertifikat beziehen**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **HTTPS aktivieren und nginx neu starten**
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **Automatische Zertifikatserneuerung**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## Erster Administrator
+
+1. Registriere dich unter `https://yourdomain.com/register`
+2. Erhöhe das Konto zum Admin in der Datenbank:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## Updates
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+## Backups
+
+```bash
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# Täglich um 2 Uhr automatisch sichern
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# Aus Backup wiederherstellen
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## Optionale Dienste
+
+| Dienst | Umgebungsvariablen | Zweck |
+| ------ | ------------------ | ----- |
+| Resend | `RESEND_API_KEY`, `FROM_EMAIL` | E-Mail-Verifizierung & Passwort-Reset (ohne dies kein Passwort-Reset möglich) |
+| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`, `STRIPE_CPA_PRICE_ID` | Abonnementabrechnung |
+| Anthropic | `ANTHROPIC_API_KEY` | KI-Transaktionsklassifizierung & Chat |
+| Etherscan | `ETHERSCAN_API_KEY` | EVM-Blockchain-Indexierung |
+| Solscan | `SOLSCAN_API_KEY` | Solana-Blockchain-Indexierung |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` | Produktanalyse |
+| Sentry | `SENTRY_DSN` | Fehlerverfolgung |
+
+## Fehlerbehebung
+
+**Dienste starten nicht**
+
+```bash
+docker compose logs api
+docker compose logs web
+docker compose logs nginx
+```
+
+**API stürzt sofort ab**
+
+Suche in den API-Logs nach `FATAL: ENCRYPTION_KEY`. Generiere den Schlüssel neu mit `openssl rand -hex 32`.
+
+**Alles zurücksetzen**
+
+
+Löscht alle Daten einschließlich der Datenbank. Erstelle zuerst ein Backup.
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/de/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/de/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..99ad9eca
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/tax-engine/cost-basis.mdx
@@ -0,0 +1,52 @@
+---
+title: Kostenbasis-Methoden
+description: FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling
+draft: false
+---
+
+## Unterstützte Methoden
+
+| Methode | ID | IRS-konform | Hinweise |
+|---------|----|-------------|---------|
+| First In, First Out | `FIFO` | ✅ Standard | Älteste Lots werden zuerst verkauft |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Specific ID muss gewählt werden |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Specific ID muss gewählt werden |
+| Specific ID | `SPECIFIC_ID` | ✅ | Manuelle Lot-Auswahl |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG, 1-jährige Haltedauer |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | Durchschnittliche Kostenbasis |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 Pool + 30-Tage-Regel |
+
+## IRS-Hinweis
+
+Der IRS erlaubt **FIFO** und **Specific Identification** für Krypto (Rev. Rul. 2023-14). LIFO und HIFO sind technisch gesehen Specific-ID-Strategien — Sie müssen Aufzeichnungen auf Lot-Ebene führen und Ihre Methode konsequent anwenden.
+
+## Verwendung
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+// Single method
+const result = computeGains(transactions, {
+ method: 'FIFO',
+ taxYear: 2024,
+});
+
+// Compare all 7 comparable methods (excludes SPECIFIC_ID)
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## Ergebnis-Struktur
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/de/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/de/tax-engine/overview.mdx
new file mode 100644
index 00000000..bb723c84
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/tax-engine/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: Tax Engine Übersicht
+description: '@dtax/tax-engine — die Kernberechnungs-Engine'
+draft: false
+---
+
+`@dtax/tax-engine` ist eine TypeScript-first-Bibliothek ohne Abhängigkeiten für die Krypto-Steuerberechnung.
+
+## Funktionen
+
+- **23 Börsen-Parser** — Format automatisch erkennen oder manuell angeben
+- **8 Kostenbasis-Methoden** — FIFO, LIFO, HIFO, Specific ID und mehr
+- **Transaktionstypen** — Kauf, Verkauf, Handel, Staking, Mining, Airdrop, NFT, DeFi, Gebühren
+- **Berichtserstellung** — Formular 8949 (CSV/PDF/TXF), Schedule D Zusammenfassung
+- **Wash-Sale-Erkennung** — kennzeichnet Verstöße gegen die 30-Tage-Wiederkaufregel
+- **Deduplizierung** — inhaltsbasierte Fingerabdruck-Duplikaterkennung
+
+## Kernfunktionen
+
+| Funktion | Beschreibung |
+|----------|--------------|
+| `parseCsv(csv, options?)` | Eine Börsen-CSV in normalisierte Transaktionen parsen |
+| `computeGains(txs, options)` | Kursgewinne für ein Steuerjahr berechnen |
+| `compareAllMethods(txs, year)` | Gewinne über alle 7 vergleichbaren Methoden vergleichen |
+| `generateForm8949Csv(disposals, options)` | Formular 8949 als CSV exportieren |
+| `generateTxfFile(disposals, options)` | TXF-Datei für Steuersoftware exportieren |
+
+## TypeScript-Typen
+
+```typescript
+type CsvFormat =
+ | 'coinbase' | 'binance' | 'binance_us' | 'kraken' | 'gemini'
+ | 'crypto_com' | 'kucoin' | 'okx' | 'bybit' | 'gate' | 'bitget'
+ | 'mexc' | 'htx' | 'etherscan' | 'etherscan_erc20'
+ | 'solscan' | 'solscan_defi' | 'bitfinex' | 'poloniex'
+ | 'koinly' | 'cointracker' | 'cryptact' | 'generic';
+
+type CostBasisMethod =
+ | 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID'
+ | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string; // ISO 8601
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/de/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/de/tax-engine/parsers.mdx
new file mode 100644
index 00000000..aa45aa0b
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/tax-engine/parsers.mdx
@@ -0,0 +1,83 @@
+---
+title: Börsen-Parser
+description: Unterstützte CSV-Exportformate von 23 Börsen und Blockchains
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## Unterstützte Börsen
+
+| Börse | Format-ID | Hinweise |
+|-------|-----------|---------|
+| Coinbase / Coinbase Pro | `coinbase` | Transaktionen + Fills |
+| Binance International | `binance` | Spot + Konvertierungsverlauf |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | Ledger-Export |
+| Gemini | `gemini` | Transaktionsverlauf |
+| Crypto.com | `crypto_com` | App-Export |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## Blockchain-Explorer
+
+| Quelle | Format-ID | Hinweise |
+|--------|-----------|---------|
+| Etherscan (Transaktionen) | `etherscan` | Erfordert `userAddress` + `nativeAsset` |
+| Etherscan (ERC-20 Token) | `etherscan_erc20` | Erfordert `userAddress` |
+| Solscan (SOL-Transfers) | `solscan` | Erfordert `userAddress` |
+| Solscan (DeFi) | `solscan_defi` | |
+
+## Import-Tools
+
+| Tool | Format-ID |
+|------|-----------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| Generic CSV | `generic` |
+
+## Verwendung
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+// Specific format
+const result = parseCsv(csv, { format: 'kraken' });
+
+// Etherscan with wallet address
+const result = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH', // or 'BNB', 'MATIC', 'AVAX', 'FTM'
+});
+
+// Auto-detect
+const result = parseCsv(csv);
+console.log(result.summary.format); // detected format
+```
+
+## Generisches CSV-Format
+
+Wenn Ihre Börse nicht aufgeführt ist, verwenden Sie das Format `generic`. Ihre CSV muss diese Spalten enthalten:
+
+| Spalte | Pflichtfeld | Beschreibung |
+|--------|-------------|--------------|
+| `Date` | ✅ | ISO 8601 oder MM/DD/YYYY |
+| `Type` | ✅ | BUY, SELL, TRADE, etc. |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[CSV-Vorlage herunterladen](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/de/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/de/tax-engine/reports.mdx
new file mode 100644
index 00000000..22f86ea2
--- /dev/null
+++ b/apps/docs-site/src/content/docs/de/tax-engine/reports.mdx
@@ -0,0 +1,34 @@
+---
+title: Berichtserstellung
+description: Formular 8949, Schedule D, TXF und PDF-Berichtserstellung
+draft: false
+---
+
+## Formular 8949 (CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+// Returns RFC 4180 CSV string ready to import into tax software
+```
+
+## TXF-Export
+
+TXF (Tax Exchange Format) wird von TurboTax, H&R Block und TaxAct unterstützt:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+// Returns TXF string — save as .txf and import into your tax software
+```
+
+## Schedule D Zusammenfassung
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/en/api/authentication.mdx b/apps/docs-site/src/content/docs/en/api/authentication.mdx
new file mode 100644
index 00000000..f494fde7
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/api/authentication.mdx
@@ -0,0 +1,44 @@
+---
+title: Authentication
+description: How to authenticate with the dTax REST API
+draft: false
+---
+
+The dTax API uses **HttpOnly session cookies** for authentication. This prevents XSS token theft.
+
+## Sign up / Login
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+```
+
+The response sets a `session` HttpOnly cookie valid for 7 days.
+
+## Using the cookie
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions \
+ -b cookies.txt
+```
+
+## OAuth
+
+Google and GitHub OAuth are also supported:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+Both redirect to `getdtax.com/auth/callback` on success.
diff --git a/apps/docs-site/src/content/docs/en/api/overview.mdx b/apps/docs-site/src/content/docs/en/api/overview.mdx
new file mode 100644
index 00000000..60d7d110
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/api/overview.mdx
@@ -0,0 +1,48 @@
+---
+title: REST API Overview
+description: dTax managed REST API — import transactions, calculate gains, download reports
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+The dTax REST API is a managed service at **`https://getdtax.com/api/v1`**. It handles storage, computation, and report generation so you don't need to manage state yourself.
+
+## Base URL
+
+```
+https://getdtax.com/api/v1
+```
+
+## Authentication
+
+All endpoints require a session cookie obtained via `/auth/login`. See [Authentication](/api/authentication) for details.
+
+## Key endpoints
+
+| Endpoint | Description |
+|----------|-------------|
+| `POST /transactions/import` | Upload CSV, auto-parse, deduplicate, store |
+| `GET /transactions` | List user's transactions with filters |
+| `GET /tax/summary` | Capital gains summary for a tax year |
+| `POST /tax/calculate` | Run full gain calculation |
+| `GET /tax/reports/:id/download` | Download Form 8949 / TXF / PDF |
+| `GET /notifications` | User notification feed |
+
+## OpenAPI specification
+
+The full OpenAPI 3.1 spec is available:
+
+
+
+## Rate limits
+
+| Plan | Limit |
+|------|-------|
+| FREE | 50 transactions, 5 AI messages/day |
+| PRO ($49/mo) | Unlimited |
+| CPA ($499/yr) | Unlimited + 10 client accounts |
diff --git a/apps/docs-site/src/content/docs/en/index.mdx b/apps/docs-site/src/content/docs/en/index.mdx
new file mode 100644
index 00000000..d3eea5fb
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/index.mdx
@@ -0,0 +1,35 @@
+---
+title: dTax Developer Hub
+description: Open-source crypto tax engine — 23 exchange parsers, 8 cost-basis methods, Form 8949 / TXF export.
+template: splash
+hero:
+ tagline: Professional-grade crypto tax calculations as an npm package.
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: Get Started
+ link: introduction
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ Zero-dependency TypeScript library. Parse CSVs, compute capital gains, export Form 8949 / TXF.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit, and 15 more.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+ Free for open-source use. Commercial license available for SaaS products.
+
+
diff --git a/apps/docs-site/src/content/docs/en/introduction.mdx b/apps/docs-site/src/content/docs/en/introduction.mdx
new file mode 100644
index 00000000..da91ee24
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: Introduction
+description: What is dTax and the dtax.dev developer hub
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# dTax Developer Hub
+
+**dTax** is an open-core crypto tax platform. The core calculation engine is AGPL-3.0 licensed and available as an npm package — so you can integrate professional-grade crypto tax calculations into your own applications.
+
+## What's here
+
+
+
+ A zero-dependency TypeScript library for parsing exchange CSVs and computing capital gains using any cost-basis method.
+
+
+ A managed API for importing transactions, running tax calculations, and generating Form 8949 / TXF reports — no infrastructure required.
+
+
+ Built-in parsers for Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit, and 15 more.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+
+## Open Core model
+
+| Layer | License | Access |
+|-------|---------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | Public on GitHub + npm |
+| REST API | Commercial | getdtax.com |
+| Web App | Commercial | getdtax.com |
+
+If you use the tax engine in a commercial product, you must open-source your changes (AGPL-3.0) **or** contact us for a commercial license.
diff --git a/apps/docs-site/src/content/docs/en/quickstart.mdx b/apps/docs-site/src/content/docs/en/quickstart.mdx
new file mode 100644
index 00000000..a554c8dc
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: Quick Start
+description: Install @dtax/tax-engine and compute your first capital gain in 5 minutes
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## Install
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## Parse a CSV and compute gains
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## Auto-detect format
+
+If you don't know which exchange generated the CSV, omit the `format` option:
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`); // e.g. "coinbase"
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Generate Form 8949
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/en/resources/csv-format.mdx b/apps/docs-site/src/content/docs/en/resources/csv-format.mdx
new file mode 100644
index 00000000..8aeec1e7
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/resources/csv-format.mdx
@@ -0,0 +1,46 @@
+---
+title: Generic CSV Format
+description: How to format a CSV for import if your exchange isn't supported
+draft: false
+---
+
+import { Steps } from '@astrojs/starlight/components';
+
+If your exchange isn't in the [parser list](/tax-engine/parsers), you can use our generic CSV format.
+
+## Download the template
+
+[Download CSV Template](https://getdtax.com/csv-template.csv)
+
+## Column reference
+
+| Column | Required | Type | Example |
+|--------|----------|------|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | enum (see below) | `BUY` |
+| `Sent Amount` | — | decimal | `0.5` |
+| `Sent Currency` | — | ticker | `BTC` |
+| `Sent Value USD` | — | decimal | `25000.00` |
+| `Received Amount` | — | decimal | `10000` |
+| `Received Currency` | — | ticker | `USDC` |
+| `Received Value USD` | — | decimal | `10000.00` |
+| `Fee Amount` | — | decimal | `0.001` |
+| `Fee Currency` | — | ticker | `ETH` |
+| `Fee Value USD` | — | decimal | `2.50` |
+| `Notes` | — | string | `Sold on Uniswap` |
+
+## Transaction types
+
+| Type | Description |
+|------|-------------|
+| `BUY` | Purchase crypto with fiat |
+| `SELL` | Sell crypto for fiat |
+| `TRADE` | Crypto-to-crypto swap |
+| `TRANSFER_IN` | Receive from another wallet (not taxable) |
+| `TRANSFER_OUT` | Send to another wallet (not taxable) |
+| `STAKING` | Staking rewards received |
+| `MINING` | Mining rewards |
+| `AIRDROP` | Airdrop received |
+| `INCOME` | Other crypto income |
+| `FEE` | Standalone fee |
+| `UNKNOWN` | Will be auto-classified by AI |
diff --git a/apps/docs-site/src/content/docs/en/resources/faq.mdx b/apps/docs-site/src/content/docs/en/resources/faq.mdx
new file mode 100644
index 00000000..0e22d39b
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: Frequently Asked Questions
+description: Common questions about dTax transaction syncing, wallet support, and tax calculations
+draft: false
+---
+
+## Why are some tiny transfers missing from my transaction history?
+
+dTax automatically filters out **dust attack transactions** — micro-transfers of less than 1,000 wei (0.000001 ETH, approximately $0.003) sent to your wallet address.
+
+### What is a dust attack?
+
+A dust attack is when a malicious actor sends an extremely small amount of cryptocurrency (often just 1 wei = 0.000000001 ETH) to your wallet. The goal is to de-anonymize wallets by tracking subsequent transactions. These are not real transfers you initiated, and they have zero tax impact.
+
+### Why filter them?
+
+| Reason | Detail |
+|--------|--------|
+| **Zero tax impact** | Amounts below 1,000 wei are worth less than $0.01 and do not constitute taxable events |
+| **Not your transactions** | Dust is sent *to* you without consent — you never controlled or moved these funds |
+| **Industry standard** | CoinTracker, Koinly, and other crypto tax tools silently filter dust transfers |
+| **Cleaner records** | Eliminating spam keeps your transaction history accurate and auditable |
+
+### What is the threshold?
+
+Transfers of less than **1,000 wei** (0.000001 ETH) are filtered for `TRANSFER_IN` and `TRANSFER_OUT` transaction types. All other transaction types (swaps, trades, staking rewards, etc.) are always recorded regardless of amount.
+
+### Does this affect my tax report?
+
+No. The IRS does not require reporting of dust attacks — you did not acquire these assets intentionally, and their value is negligible. Filtering them has no effect on your Form 8949 or capital gains calculations.
+
+---
+
+## Why does price enrichment show a partial count (e.g. "9 / 50")?
+
+The price enrichment count only includes **tax-relevant transactions** (BUY, SELL, TRADE, DEX_SWAP, STAKING_REWARD, etc.). Simple transfers between your own wallets (`TRANSFER_IN` / `TRANSFER_OUT`) are excluded because they are not taxable events and do not require a USD price for tax reporting.
+
+---
+
+## Why is my wallet sync taking a long time?
+
+EVM wallet syncing queries up to 5 blockchain networks (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism) sequentially to stay within Etherscan's free-tier rate limit of 5 requests per second. Each chain performs 5 parallel API calls. A full sync across all chains may take 30–60 seconds.
+
+---
+
+## Why does my tax calculation show $0 for wallet transactions?
+
+If your wallet only contains `TRANSFER_IN` and `TRANSFER_OUT` transactions, the tax total will be $0. Transfers between your own wallets are **not taxable events** — no capital gain or loss is realized until you sell, trade, or spend the asset.
diff --git a/apps/docs-site/src/content/docs/en/resources/license.mdx b/apps/docs-site/src/content/docs/en/resources/license.mdx
new file mode 100644
index 00000000..23fefe57
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/resources/license.mdx
@@ -0,0 +1,39 @@
+---
+title: Open Core License
+description: AGPL-3.0 open core model — what you can and cannot do
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+The `@dtax/tax-engine` npm package is licensed under **GNU Affero General Public License v3.0**.
+
+### You CAN
+
+- Use it in personal projects for free
+- Study and modify the source code
+- Distribute modified versions (must remain AGPL-3.0)
+- Use it internally without open-sourcing (internal use only)
+
+### You MUST (if distributing)
+
+- Include the full AGPL-3.0 license text
+- Open-source all modifications under AGPL-3.0
+- Provide source code access to users of your service
+
+### You NEED a Commercial License if
+
+- You build a SaaS product using the engine without open-sourcing it
+- You want to keep your modifications proprietary
+
+## Commercial License
+
+Contact [hello@getdtax.com](mailto:hello@getdtax.com) for commercial licensing options.
+
+## Web App & API
+
+The dTax web application and REST API are proprietary software under the **dTax Commercial License**. They are not open source.
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/en/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/en/resources/self-hosting.mdx
new file mode 100644
index 00000000..b3c80fe0
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/resources/self-hosting.mdx
@@ -0,0 +1,263 @@
+---
+title: Self-Hosting
+description: Deploy dTax on your own server using Docker Compose — full stack with PostgreSQL, Redis, API, and Web
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Deploy dTax on your own Linux server in under 15 minutes using Docker Compose.
+
+## Prerequisites
+
+- Linux server (Ubuntu 22.04+ recommended), 2+ GB RAM
+- Docker Engine 24+ and Docker Compose v2
+- A domain name pointed to your server's IP
+- Ports 80 and 443 open in your firewall
+
+## Quick Start
+
+
+
+1. **Clone the repository**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **Configure environment**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ Edit `.env` and set all required values:
+
+ | Variable | Description |
+ | ------------------- | ----------- |
+ | `POSTGRES_PASSWORD` | Strong database password |
+ | `JWT_SECRET` | Random string, at least 32 characters |
+ | `ENCRYPTION_KEY` | **64-character hex string** — see note below |
+ | `CORS_ORIGIN` | Your domain, e.g. `https://tax.example.com` |
+ | `APP_URL` | Same domain (used in password-reset emails) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api` (**build-time**, must be set before `docker compose build`) |
+
+
+ The encryption key **must** be a 64-character hex string (32 raw bytes). The API will crash on startup if any other format is used.
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **Start services**
+
+
+ Set all variables in `.env` **before** running `docker compose build`. `NEXT_PUBLIC_*` variables are baked into the JavaScript bundle at image build time — changing them after the build has no effect.
+
+ ```bash
+ docker compose build
+ docker compose up -d
+ ```
+
+
+ This starts PostgreSQL, Redis, API, Web, and nginx. The `migrate` service runs database migrations automatically.
+
+ Verify everything is running:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## Architecture
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ routes │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS with Let's Encrypt
+
+
+
+1. **Update nginx config**
+
+ Edit `docker/nginx/nginx.conf` and replace `server_name _;` with your domain:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **Obtain certificate**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **Enable HTTPS**
+
+ Add an HTTPS server block to `docker/nginx/nginx.conf`:
+
+ ```nginx
+ server {
+ listen 443 ssl http2;
+ server_name tax.example.com;
+
+ ssl_certificate /etc/letsencrypt/live/tax.example.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/tax.example.com/privkey.pem;
+ include /etc/nginx/snippets/ssl-params.conf;
+
+ location /api/ {
+ proxy_pass http://api/api/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ }
+
+ location / {
+ proxy_pass http://web;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ }
+ ```
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **Auto-renew certificates**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## First Admin User
+
+1. Register at `https://yourdomain.com/register`
+2. Promote your account to admin:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## Updates
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+The `migrate` service runs automatically to apply new database migrations.
+
+## Backups
+
+```bash
+# Run backup
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# Schedule daily at 2am
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# Restore from backup
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## Optional Services
+
+| Service | Environment Variables | Purpose |
+| --------- | --------------------- | ------- |
+| Resend | `RESEND_API_KEY`, `FROM_EMAIL` | Email verification & password reset — without this, users cannot reset passwords or verify email |
+| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`, `STRIPE_CPA_PRICE_ID` | Subscription billing |
+| Anthropic | `ANTHROPIC_API_KEY` | AI transaction classification & chat |
+| Etherscan | `ETHERSCAN_API_KEY` | EVM blockchain indexing (Ethereum, Polygon, BSC, Arbitrum, Optimism) |
+| Solscan | `SOLSCAN_API_KEY` | Solana blockchain indexing |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` | Product analytics |
+| Sentry | `SENTRY_DSN` | Error tracking |
+
+All optional services degrade gracefully when not configured.
+
+## Troubleshooting
+
+**Services fail to start**
+
+```bash
+docker compose logs api # Check API logs
+docker compose logs web # Check Web logs
+docker compose logs nginx # Check nginx logs
+```
+
+**API crashes immediately**
+
+Check for `FATAL: ENCRYPTION_KEY` in the API logs — this means your `ENCRYPTION_KEY` is not a valid 64-character hex string. Regenerate with `openssl rand -hex 32`.
+
+**Database connection errors**
+
+Ensure `POSTGRES_PASSWORD` in `.env` matches the value used when the postgres volume was first created:
+
+```bash
+docker compose ps postgres
+docker compose logs postgres
+```
+
+**Port conflicts**
+
+If ports 80 or 443 are already in use, edit `docker-compose.yml` to change the nginx port mappings.
+
+**Out of disk space**
+
+```bash
+docker system prune -f # Remove unused images/containers
+```
+
+**Reset everything**
+
+
+This destroys all data including the database. Back up first.
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/en/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/en/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..d955f84b
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/tax-engine/cost-basis.mdx
@@ -0,0 +1,52 @@
+---
+title: Cost Basis Methods
+description: FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling
+draft: false
+---
+
+## Supported methods
+
+| Method | ID | IRS Compliant | Notes |
+|--------|----|---------------|-------|
+| First In, First Out | `FIFO` | ✅ Default | Oldest lots sold first |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Must elect Specific ID |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Must elect Specific ID |
+| Specific ID | `SPECIFIC_ID` | ✅ | Manual lot selection |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG, 1-year holding |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | Average cost basis |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 pool + 30-day rule |
+
+## IRS note
+
+The IRS allows **FIFO** and **Specific Identification** for crypto (Rev. Rul. 2023-14). LIFO and HIFO are technically Specific ID strategies — you must maintain lot-level records and consistently apply your method.
+
+## Usage
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+// Single method
+const result = computeGains(transactions, {
+ method: 'FIFO',
+ taxYear: 2024,
+});
+
+// Compare all 7 comparable methods (excludes SPECIFIC_ID)
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## Result shape
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/en/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/en/tax-engine/overview.mdx
new file mode 100644
index 00000000..e7cc5b5f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/tax-engine/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: Tax Engine Overview
+description: '@dtax/tax-engine — the core calculation engine'
+draft: false
+---
+
+`@dtax/tax-engine` is a TypeScript-first, zero-dependency library for crypto tax calculation.
+
+## Features
+
+- **23 exchange parsers** — auto-detect or manually specify format
+- **8 cost-basis methods** — FIFO, LIFO, HIFO, Specific ID, and more
+- **Transaction types** — Buy, Sell, Trade, Staking, Mining, Airdrop, NFT, DeFi, Fees
+- **Report generation** — Form 8949 (CSV/PDF/TXF), Schedule D summary
+- **Wash sale detection** — flags 30-day repurchase rule violations
+- **Deduplication** — content-fingerprint based duplicate detection
+
+## Core functions
+
+| Function | Description |
+|----------|-------------|
+| `parseCsv(csv, options?)` | Parse an exchange CSV into normalized transactions |
+| `computeGains(txs, options)` | Compute capital gains for a tax year |
+| `compareAllMethods(txs, year)` | Compare gains across all 7 comparable methods |
+| `generateForm8949Csv(disposals, options)` | Export Form 8949 as CSV |
+| `generateTxfFile(disposals, options)` | Export TXF file for tax software |
+
+## TypeScript types
+
+```typescript
+type CsvFormat =
+ | 'coinbase' | 'binance' | 'binance_us' | 'kraken' | 'gemini'
+ | 'crypto_com' | 'kucoin' | 'okx' | 'bybit' | 'gate' | 'bitget'
+ | 'mexc' | 'htx' | 'etherscan' | 'etherscan_erc20'
+ | 'solscan' | 'solscan_defi' | 'bitfinex' | 'poloniex'
+ | 'koinly' | 'cointracker' | 'cryptact' | 'generic';
+
+type CostBasisMethod =
+ | 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID'
+ | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string; // ISO 8601
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/en/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/en/tax-engine/parsers.mdx
new file mode 100644
index 00000000..af9f4b79
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/tax-engine/parsers.mdx
@@ -0,0 +1,83 @@
+---
+title: Exchange Parsers
+description: Supported CSV export formats from 23 exchanges and blockchains
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## Supported exchanges
+
+| Exchange | Format ID | Notes |
+|----------|-----------|-------|
+| Coinbase / Coinbase Pro | `coinbase` | Transactions + fills |
+| Binance International | `binance` | Spot + convert history |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | Ledger export |
+| Gemini | `gemini` | Transaction history |
+| Crypto.com | `crypto_com` | App export |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## Blockchain explorers
+
+| Source | Format ID | Notes |
+|--------|-----------|-------|
+| Etherscan (Transactions) | `etherscan` | Requires `userAddress` + `nativeAsset` |
+| Etherscan (ERC-20 Tokens) | `etherscan_erc20` | Requires `userAddress` |
+| Solscan (SOL Transfers) | `solscan` | Requires `userAddress` |
+| Solscan (DeFi) | `solscan_defi` | |
+
+## Import tools
+
+| Tool | Format ID |
+|------|-----------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| Generic CSV | `generic` |
+
+## Usage
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+// Specific format
+const result = parseCsv(csv, { format: 'kraken' });
+
+// Etherscan with wallet address
+const result = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH', // or 'BNB', 'MATIC', 'AVAX', 'FTM'
+});
+
+// Auto-detect
+const result = parseCsv(csv);
+console.log(result.summary.format); // detected format
+```
+
+## Generic CSV format
+
+If your exchange isn't listed, use the `generic` format. Your CSV must have these columns:
+
+| Column | Required | Description |
+|--------|----------|-------------|
+| `Date` | ✅ | ISO 8601 or MM/DD/YYYY |
+| `Type` | ✅ | BUY, SELL, TRADE, etc. |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[Download CSV template](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/en/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/en/tax-engine/reports.mdx
new file mode 100644
index 00000000..338590bc
--- /dev/null
+++ b/apps/docs-site/src/content/docs/en/tax-engine/reports.mdx
@@ -0,0 +1,34 @@
+---
+title: Report Generation
+description: Form 8949, Schedule D, TXF, and PDF report generation
+draft: false
+---
+
+## Form 8949 (CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+// Returns RFC 4180 CSV string ready to import into tax software
+```
+
+## TXF export
+
+TXF (Tax Exchange Format) is supported by TurboTax, H&R Block, and TaxAct:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+// Returns TXF string — save as .txf and import into your tax software
+```
+
+## Schedule D summary
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/es/api/authentication.mdx b/apps/docs-site/src/content/docs/es/api/authentication.mdx
new file mode 100644
index 00000000..2e6f7341
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/api/authentication.mdx
@@ -0,0 +1,44 @@
+---
+title: Autenticación
+description: Cómo autenticarse con la REST API de dTax
+draft: false
+---
+
+La API de dTax usa **cookies de sesión HttpOnly** para la autenticación. Esto previene el robo de tokens mediante XSS.
+
+## Registro / Inicio de sesión
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+```
+
+La respuesta establece una cookie `session` HttpOnly válida por 7 días.
+
+## Usar la cookie
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions \
+ -b cookies.txt
+```
+
+## OAuth
+
+Google y GitHub OAuth también son compatibles:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+Ambos redirigen a `getdtax.com/auth/callback` al completarse correctamente.
diff --git a/apps/docs-site/src/content/docs/es/api/overview.mdx b/apps/docs-site/src/content/docs/es/api/overview.mdx
new file mode 100644
index 00000000..30822419
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/api/overview.mdx
@@ -0,0 +1,48 @@
+---
+title: Descripción General de la REST API
+description: REST API gestionada de dTax — importa transacciones, calcula ganancias, descarga reportes
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+La REST API de dTax es un servicio gestionado en **`https://getdtax.com/api/v1`**. Se encarga del almacenamiento, cálculo y generación de reportes para que no tengas que gestionar el estado tú mismo.
+
+## URL Base
+
+```
+https://getdtax.com/api/v1
+```
+
+## Autenticación
+
+Todos los endpoints requieren una cookie de sesión obtenida mediante `/auth/login`. Consulta [Autenticación](/api/authentication) para más detalles.
+
+## Endpoints principales
+
+| Endpoint | Descripción |
+|----------|-------------|
+| `POST /transactions/import` | Sube CSV, parsea automáticamente, deduplica y almacena |
+| `GET /transactions` | Lista las transacciones del usuario con filtros |
+| `GET /tax/summary` | Resumen de ganancias de capital para un año fiscal |
+| `POST /tax/calculate` | Ejecuta el cálculo completo de ganancias |
+| `GET /tax/reports/:id/download` | Descarga Form 8949 / TXF / PDF |
+| `GET /notifications` | Feed de notificaciones del usuario |
+
+## Especificación OpenAPI
+
+La especificación completa OpenAPI 3.1 está disponible:
+
+
+
+## Límites de uso
+
+| Plan | Límite |
+|------|--------|
+| FREE | 50 transacciones, 5 mensajes de IA/día |
+| PRO ($49/mo) | Sin límite |
+| CPA ($499/yr) | Sin límite + 10 cuentas de clientes |
diff --git a/apps/docs-site/src/content/docs/es/index.mdx b/apps/docs-site/src/content/docs/es/index.mdx
new file mode 100644
index 00000000..db54b11c
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/index.mdx
@@ -0,0 +1,35 @@
+---
+title: Centro de Desarrolladores de dTax
+description: Motor de impuestos cripto de código abierto — 23 parsers de exchanges, 8 métodos de base de costo, exportación Form 8949 / TXF.
+template: splash
+hero:
+ tagline: Cálculos de impuestos cripto de nivel profesional como paquete npm.
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: Comenzar
+ link: introduction
+ icon: right-arrow
+ variant: primary
+ - text: Ver en GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ Librería TypeScript sin dependencias. Parsea CSV, calcula ganancias de capital, exporta Form 8949 / TXF.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit y 15 más.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+ Gratuito para uso de código abierto. Licencia comercial disponible para productos SaaS.
+
+
diff --git a/apps/docs-site/src/content/docs/es/introduction.mdx b/apps/docs-site/src/content/docs/es/introduction.mdx
new file mode 100644
index 00000000..3089cd7e
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: Introducción
+description: Qué es dTax y el centro de desarrolladores dtax.dev
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# Centro de Desarrolladores de dTax
+
+**dTax** es una plataforma de impuestos cripto de modelo open core. El motor de cálculo principal tiene licencia AGPL-3.0 y está disponible como paquete npm — para que puedas integrar cálculos de impuestos cripto de nivel profesional en tus propias aplicaciones.
+
+## Qué hay aquí
+
+
+
+ Una librería TypeScript sin dependencias para parsear CSV de exchanges y calcular ganancias de capital usando cualquier método de base de costo.
+
+
+ Una API gestionada para importar transacciones, ejecutar cálculos de impuestos y generar reportes Form 8949 / TXF — sin necesidad de infraestructura propia.
+
+
+ Parsers integrados para Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit y 15 más.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+
+## Modelo Open Core
+
+| Capa | Licencia | Acceso |
+|------|----------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | Público en GitHub + npm |
+| REST API | Comercial | getdtax.com |
+| Web App | Comercial | getdtax.com |
+
+Si usas el motor de impuestos en un producto comercial, debes publicar tus cambios como código abierto (AGPL-3.0) **o** contactarnos para obtener una licencia comercial.
diff --git a/apps/docs-site/src/content/docs/es/quickstart.mdx b/apps/docs-site/src/content/docs/es/quickstart.mdx
new file mode 100644
index 00000000..e8496634
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: Inicio Rápido
+description: Instala @dtax/tax-engine y calcula tu primera ganancia de capital en 5 minutos
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## Instalar
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## Parsear un CSV y calcular ganancias
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## Detección automática de formato
+
+Si no sabes qué exchange generó el CSV, omite la opción `format`:
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`); // e.g. "coinbase"
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Generar Form 8949
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/es/resources/csv-format.mdx b/apps/docs-site/src/content/docs/es/resources/csv-format.mdx
new file mode 100644
index 00000000..3621c7da
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/resources/csv-format.mdx
@@ -0,0 +1,46 @@
+---
+title: Formato CSV Genérico
+description: Cómo formatear un CSV para importación si tu exchange no está soportado
+draft: false
+---
+
+import { Steps } from '@astrojs/starlight/components';
+
+Si tu exchange no está en la [lista de parsers](/tax-engine/parsers), puedes usar nuestro formato CSV genérico.
+
+## Descargar la plantilla
+
+[Descargar plantilla CSV](https://getdtax.com/csv-template.csv)
+
+## Referencia de columnas
+
+| Columna | Requerida | Tipo | Ejemplo |
+|---------|-----------|------|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | enum (ver abajo) | `BUY` |
+| `Sent Amount` | — | decimal | `0.5` |
+| `Sent Currency` | — | ticker | `BTC` |
+| `Sent Value USD` | — | decimal | `25000.00` |
+| `Received Amount` | — | decimal | `10000` |
+| `Received Currency` | — | ticker | `USDC` |
+| `Received Value USD` | — | decimal | `10000.00` |
+| `Fee Amount` | — | decimal | `0.001` |
+| `Fee Currency` | — | ticker | `ETH` |
+| `Fee Value USD` | — | decimal | `2.50` |
+| `Notes` | — | string | `Sold on Uniswap` |
+
+## Tipos de transacción
+
+| Tipo | Descripción |
+|------|-------------|
+| `BUY` | Compra de cripto con fiat |
+| `SELL` | Venta de cripto por fiat |
+| `TRADE` | Intercambio de cripto a cripto |
+| `TRANSFER_IN` | Recepción desde otra billetera (no tributable) |
+| `TRANSFER_OUT` | Envío a otra billetera (no tributable) |
+| `STAKING` | Recompensas de staking recibidas |
+| `MINING` | Recompensas de minería |
+| `AIRDROP` | Airdrop recibido |
+| `INCOME` | Otros ingresos en cripto |
+| `FEE` | Comisión independiente |
+| `UNKNOWN` | Será clasificado automáticamente por IA |
diff --git a/apps/docs-site/src/content/docs/es/resources/faq.mdx b/apps/docs-site/src/content/docs/es/resources/faq.mdx
new file mode 100644
index 00000000..ea5ca915
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: Preguntas frecuentes
+description: Preguntas comunes sobre la sincronización de transacciones, soporte de billeteras y cálculos fiscales en dTax
+draft: false
+---
+
+## ¿Por qué faltan algunas transferencias pequeñas en mi historial de transacciones?
+
+dTax filtra automáticamente las **transacciones de dust attack** — microtransferencias de menos de 1.000 wei (0,000001 ETH, aproximadamente $0,003) enviadas a la dirección de tu billetera.
+
+### ¿Qué es un dust attack?
+
+Un dust attack ocurre cuando un actor malicioso envía una cantidad extremadamente pequeña de criptomoneda (a menudo solo 1 wei = 0,000000001 ETH) a tu billetera. El objetivo es desanonimizar billeteras rastreando transacciones posteriores. Estas no son transferencias que hayas iniciado y no tienen ningún impacto fiscal.
+
+### ¿Por qué filtrarlas?
+
+| Razón | Detalle |
+|-------|---------|
+| **Impacto fiscal cero** | Los montos inferiores a 1.000 wei valen menos de $0,01 y no constituyen eventos imponibles |
+| **No son tus transacciones** | El dust se envía *a ti sin tu consentimiento* — nunca controlaste ni moviste esos fondos |
+| **Estándar de la industria** | CoinTracker, Koinly y otras herramientas fiscales de cripto filtran silenciosamente las transferencias de dust |
+| **Historial más limpio** | Eliminar el spam hace que tu historial de transacciones sea más preciso y fácil de auditar |
+
+### ¿Cuál es el umbral?
+
+Las transferencias de menos de **1.000 wei** (0,000001 ETH) se filtran para los tipos de transacción `TRANSFER_IN` y `TRANSFER_OUT`. Todos los demás tipos de transacción (swaps, operaciones, recompensas de staking, etc.) siempre se registran independientemente del monto.
+
+### ¿Esto afecta mi informe fiscal?
+
+No. El IRS no requiere reportar dust attacks — no adquiriste estos activos intencionalmente y su valor es insignificante. El filtrado no tiene ningún efecto en tu Formulario 8949 ni en los cálculos de ganancias de capital.
+
+---
+
+## ¿Por qué el enriquecimiento de precios muestra un número parcial (p. ej., "9 / 50")?
+
+El recuento de enriquecimiento de precios solo incluye **transacciones imponibles** (BUY, SELL, TRADE, DEX_SWAP, STAKING_REWARD, etc.). Las transferencias simples entre tus propias billeteras (`TRANSFER_IN` / `TRANSFER_OUT`) se excluyen porque no son eventos imponibles y no requieren un precio en USD para la declaración fiscal.
+
+---
+
+## ¿Por qué la sincronización de mi billetera tarda tanto?
+
+La sincronización de billeteras EVM consulta hasta 5 redes blockchain (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism) de forma secuencial para mantenerse dentro del límite de velocidad del plan gratuito de Etherscan de 5 solicitudes por segundo. Cada cadena realiza 5 llamadas API en paralelo. Una sincronización completa de todas las cadenas puede tardar entre 30 y 60 segundos.
+
+---
+
+## ¿Por qué mi cálculo fiscal muestra $0 para las transacciones de billetera?
+
+Si tu billetera solo contiene transacciones `TRANSFER_IN` y `TRANSFER_OUT`, el total fiscal será $0. Las transferencias entre tus propias billeteras **no son eventos imponibles** — no se realiza ninguna ganancia o pérdida de capital hasta que vendes, intercambias o gastas el activo.
diff --git a/apps/docs-site/src/content/docs/es/resources/license.mdx b/apps/docs-site/src/content/docs/es/resources/license.mdx
new file mode 100644
index 00000000..c469207d
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/resources/license.mdx
@@ -0,0 +1,39 @@
+---
+title: Licencia Open Core
+description: Modelo open core AGPL-3.0 — qué puedes y no puedes hacer
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+El paquete npm `@dtax/tax-engine` está licenciado bajo la **GNU Affero General Public License v3.0**.
+
+### Puedes
+
+- Usarlo en proyectos personales de forma gratuita
+- Estudiar y modificar el código fuente
+- Distribuir versiones modificadas (deben mantenerse bajo AGPL-3.0)
+- Usarlo internamente sin publicar el código fuente (solo uso interno)
+
+### Debes (si distribuyes)
+
+- Incluir el texto completo de la licencia AGPL-3.0
+- Publicar todas las modificaciones bajo AGPL-3.0
+- Proporcionar acceso al código fuente a los usuarios de tu servicio
+
+### Necesitas una Licencia Comercial si
+
+- Construyes un producto SaaS usando el motor sin publicar el código fuente
+- Quieres mantener tus modificaciones como código propietario
+
+## Licencia Comercial
+
+Contacta a [hello@getdtax.com](mailto:hello@getdtax.com) para opciones de licenciamiento comercial.
+
+## Web App y API
+
+La aplicación web y la REST API de dTax son software propietario bajo la **dTax Commercial License**. No son de código abierto.
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/es/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/es/resources/self-hosting.mdx
new file mode 100644
index 00000000..b4529da1
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/resources/self-hosting.mdx
@@ -0,0 +1,202 @@
+---
+title: Auto-alojamiento
+description: Despliega dTax en tu propio servidor con Docker Compose — stack completo con PostgreSQL, Redis, API y Web
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Despliega dTax en tu servidor Linux en menos de 15 minutos con Docker Compose.
+
+## Requisitos previos
+
+- Servidor Linux (Ubuntu 22.04+ recomendado), 2+ GB de RAM
+- Docker Engine 24+ y Docker Compose v2
+- Un nombre de dominio apuntando a la IP del servidor
+- Puertos 80 y 443 abiertos en el firewall
+
+## Inicio rápido
+
+
+
+1. **Clonar el repositorio**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **Configurar variables de entorno**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ Edita `.env` y establece todos los valores requeridos:
+
+ | Variable | Descripción |
+ | -------- | ----------- |
+ | `POSTGRES_PASSWORD` | Contraseña robusta para la base de datos |
+ | `JWT_SECRET` | Cadena aleatoria, mínimo 32 caracteres |
+ | `ENCRYPTION_KEY` | **Cadena hexadecimal de 64 caracteres** — ver nota abajo |
+ | `CORS_ORIGIN` | Tu dominio, ej. `https://tax.example.com` |
+ | `APP_URL` | Mismo dominio (usado en emails de restablecimiento) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api` (**variable de compilación** — debe configurarse antes de `docker compose build`) |
+
+
+ La clave de cifrado **debe** ser una cadena hexadecimal de 64 caracteres (32 bytes sin procesar). Cualquier otro formato hará que la API falle al arrancar.
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **Iniciar servicios**
+
+ ```bash
+ docker compose up -d
+ ```
+
+ Inicia PostgreSQL, Redis, API, Web y nginx. El servicio `migrate` ejecuta las migraciones de base de datos automáticamente.
+
+ Verificar funcionamiento:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## Arquitectura
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ Rutas │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS con Let's Encrypt
+
+
+
+1. **Actualizar configuración nginx**
+
+ Edita `docker/nginx/nginx.conf` y reemplaza `server_name _;` con tu dominio:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **Obtener certificado**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **Habilitar HTTPS y reiniciar nginx**
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **Renovación automática de certificados**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## Primer administrador
+
+1. Regístrate en `https://yourdomain.com/register`
+2. Promueve la cuenta a administrador en la base de datos:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## Actualizaciones
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+## Copias de seguridad
+
+```bash
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# Copia de seguridad diaria a las 2am
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# Restaurar desde copia de seguridad
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## Servicios opcionales
+
+| Servicio | Variables de entorno | Propósito |
+| -------- | -------------------- | --------- |
+| Resend | `RESEND_API_KEY`, `FROM_EMAIL` | Verificación de email y restablecimiento de contraseña (sin esto no es posible restablecer contraseñas) |
+| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`, `STRIPE_CPA_PRICE_ID` | Facturación de suscripciones |
+| Anthropic | `ANTHROPIC_API_KEY` | Clasificación de transacciones con IA y chat |
+| Etherscan | `ETHERSCAN_API_KEY` | Indexación blockchain EVM |
+| Solscan | `SOLSCAN_API_KEY` | Indexación blockchain Solana |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` | Analítica de producto |
+| Sentry | `SENTRY_DSN` | Seguimiento de errores |
+
+## Solución de problemas
+
+**Los servicios no arrancan**
+
+```bash
+docker compose logs api
+docker compose logs web
+docker compose logs nginx
+```
+
+**La API falla inmediatamente**
+
+Busca `FATAL: ENCRYPTION_KEY` en los logs de la API. Regenera la clave con `openssl rand -hex 32`.
+
+**Restablecer todo**
+
+
+Elimina todos los datos incluyendo la base de datos. Haz una copia de seguridad primero.
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/es/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/es/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..ac673da0
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/tax-engine/cost-basis.mdx
@@ -0,0 +1,52 @@
+---
+title: Métodos de Base de Costo
+description: FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling
+draft: false
+---
+
+## Métodos compatibles
+
+| Método | ID | Cumple IRS | Notas |
+|--------|----|------------|-------|
+| First In, First Out | `FIFO` | ✅ Predeterminado | Los lotes más antiguos se venden primero |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Debe elegir Specific ID |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Debe elegir Specific ID |
+| Specific ID | `SPECIFIC_ID` | ✅ | Selección manual de lotes |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG, período de tenencia de 1 año |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | Base de costo promedio |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 pool + regla de 30 días |
+
+## Nota sobre el IRS
+
+El IRS permite **FIFO** e **Identificación Específica** para cripto (Rev. Rul. 2023-14). LIFO y HIFO son técnicamente estrategias de Specific ID — debes mantener registros a nivel de lote y aplicar tu método de forma consistente.
+
+## Uso
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+// Single method
+const result = computeGains(transactions, {
+ method: 'FIFO',
+ taxYear: 2024,
+});
+
+// Compare all 7 comparable methods (excludes SPECIFIC_ID)
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## Estructura del resultado
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/es/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/es/tax-engine/overview.mdx
new file mode 100644
index 00000000..25c623e1
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/tax-engine/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: Descripción General del Motor de Impuestos
+description: '@dtax/tax-engine — el motor de cálculo principal'
+draft: false
+---
+
+`@dtax/tax-engine` es una librería TypeScript-first sin dependencias para el cálculo de impuestos cripto.
+
+## Características
+
+- **23 parsers de exchanges** — detección automática o especificación manual del formato
+- **8 métodos de base de costo** — FIFO, LIFO, HIFO, Specific ID y más
+- **Tipos de transacción** — Compra, Venta, Intercambio, Staking, Minería, Airdrop, NFT, DeFi, Comisiones
+- **Generación de reportes** — Form 8949 (CSV/PDF/TXF), resumen Schedule D
+- **Detección de wash sale** — identifica violaciones de la regla de recompra de 30 días
+- **Deduplicación** — detección de duplicados basada en huella de contenido
+
+## Funciones principales
+
+| Función | Descripción |
+|---------|-------------|
+| `parseCsv(csv, options?)` | Parsea un CSV de exchange en transacciones normalizadas |
+| `computeGains(txs, options)` | Calcula ganancias de capital para un año fiscal |
+| `compareAllMethods(txs, year)` | Compara ganancias entre los 7 métodos comparables |
+| `generateForm8949Csv(disposals, options)` | Exporta Form 8949 como CSV |
+| `generateTxfFile(disposals, options)` | Exporta archivo TXF para software fiscal |
+
+## Tipos TypeScript
+
+```typescript
+type CsvFormat =
+ | 'coinbase' | 'binance' | 'binance_us' | 'kraken' | 'gemini'
+ | 'crypto_com' | 'kucoin' | 'okx' | 'bybit' | 'gate' | 'bitget'
+ | 'mexc' | 'htx' | 'etherscan' | 'etherscan_erc20'
+ | 'solscan' | 'solscan_defi' | 'bitfinex' | 'poloniex'
+ | 'koinly' | 'cointracker' | 'cryptact' | 'generic';
+
+type CostBasisMethod =
+ | 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID'
+ | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string; // ISO 8601
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/es/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/es/tax-engine/parsers.mdx
new file mode 100644
index 00000000..4951be61
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/tax-engine/parsers.mdx
@@ -0,0 +1,83 @@
+---
+title: Parsers de Exchanges
+description: Formatos CSV de exportación compatibles de 23 exchanges y blockchains
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## Exchanges compatibles
+
+| Exchange | ID de formato | Notas |
+|----------|---------------|-------|
+| Coinbase / Coinbase Pro | `coinbase` | Transacciones + órdenes ejecutadas |
+| Binance International | `binance` | Historial spot + conversiones |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | Exportación del libro de transacciones |
+| Gemini | `gemini` | Historial de transacciones |
+| Crypto.com | `crypto_com` | Exportación desde la app |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## Exploradores de blockchain
+
+| Fuente | ID de formato | Notas |
+|--------|---------------|-------|
+| Etherscan (Transacciones) | `etherscan` | Requiere `userAddress` + `nativeAsset` |
+| Etherscan (Tokens ERC-20) | `etherscan_erc20` | Requiere `userAddress` |
+| Solscan (Transferencias SOL) | `solscan` | Requiere `userAddress` |
+| Solscan (DeFi) | `solscan_defi` | |
+
+## Herramientas de importación
+
+| Herramienta | ID de formato |
+|-------------|---------------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| Generic CSV | `generic` |
+
+## Uso
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+// Specific format
+const result = parseCsv(csv, { format: 'kraken' });
+
+// Etherscan with wallet address
+const result = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH', // or 'BNB', 'MATIC', 'AVAX', 'FTM'
+});
+
+// Auto-detect
+const result = parseCsv(csv);
+console.log(result.summary.format); // detected format
+```
+
+## Formato CSV genérico
+
+Si tu exchange no está en la lista, usa el formato `generic`. Tu CSV debe tener estas columnas:
+
+| Columna | Requerida | Descripción |
+|---------|-----------|-------------|
+| `Date` | ✅ | ISO 8601 o MM/DD/YYYY |
+| `Type` | ✅ | BUY, SELL, TRADE, etc. |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[Descargar plantilla CSV](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/es/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/es/tax-engine/reports.mdx
new file mode 100644
index 00000000..474e9f96
--- /dev/null
+++ b/apps/docs-site/src/content/docs/es/tax-engine/reports.mdx
@@ -0,0 +1,34 @@
+---
+title: Generación de Reportes
+description: Generación de reportes Form 8949, Schedule D, TXF y PDF
+draft: false
+---
+
+## Form 8949 (CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+// Returns RFC 4180 CSV string ready to import into tax software
+```
+
+## Exportación TXF
+
+TXF (Tax Exchange Format) es compatible con TurboTax, H&R Block y TaxAct:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+// Returns TXF string — save as .txf and import into your tax software
+```
+
+## Resumen Schedule D
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/fr/api/authentication.mdx b/apps/docs-site/src/content/docs/fr/api/authentication.mdx
new file mode 100644
index 00000000..d4b3bd98
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/api/authentication.mdx
@@ -0,0 +1,44 @@
+---
+title: Authentification
+description: Comment s'authentifier auprès de l'API REST dTax
+draft: false
+---
+
+L'API dTax utilise des **cookies de session HttpOnly** pour l'authentification. Cela prévient le vol de jetons par XSS.
+
+## Inscription / Connexion
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+```
+
+La réponse définit un cookie HttpOnly `session` valable 7 jours.
+
+## Utilisation du cookie
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions \
+ -b cookies.txt
+```
+
+## OAuth
+
+Google et GitHub OAuth sont également pris en charge :
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+Les deux redirigent vers `getdtax.com/auth/callback` en cas de succès.
diff --git a/apps/docs-site/src/content/docs/fr/api/overview.mdx b/apps/docs-site/src/content/docs/fr/api/overview.mdx
new file mode 100644
index 00000000..f3ebdf77
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/api/overview.mdx
@@ -0,0 +1,48 @@
+---
+title: Aperçu de l'API REST
+description: API REST gérée par dTax — importez des transactions, calculez les plus-values, téléchargez des rapports
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+L'API REST dTax est un service géré disponible à **`https://getdtax.com/api/v1`**. Elle prend en charge le stockage, le calcul et la génération de rapports, vous n'avez donc pas besoin de gérer l'état vous-même.
+
+## URL de base
+
+```
+https://getdtax.com/api/v1
+```
+
+## Authentification
+
+Tous les endpoints nécessitent un cookie de session obtenu via `/auth/login`. Consultez [Authentification](/fr/api/authentication) pour plus de détails.
+
+## Endpoints principaux
+
+| Endpoint | Description |
+|----------|-------------|
+| `POST /transactions/import` | Charger un CSV, parser automatiquement, dédupliquer, stocker |
+| `GET /transactions` | Lister les transactions de l'utilisateur avec des filtres |
+| `GET /tax/summary` | Résumé des plus-values pour une année fiscale |
+| `POST /tax/calculate` | Exécuter le calcul complet des gains |
+| `GET /tax/reports/:id/download` | Télécharger Form 8949 / TXF / PDF |
+| `GET /notifications` | Fil de notifications de l'utilisateur |
+
+## Spécification OpenAPI
+
+La spécification complète OpenAPI 3.1 est disponible :
+
+
+
+## Limites de débit
+
+| Forfait | Limite |
+|---------|--------|
+| FREE | 50 transactions, 5 messages IA/jour |
+| PRO (49 $/mois) | Illimité |
+| CPA (499 $/an) | Illimité + 10 comptes clients |
diff --git a/apps/docs-site/src/content/docs/fr/index.mdx b/apps/docs-site/src/content/docs/fr/index.mdx
new file mode 100644
index 00000000..51a6b85f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/index.mdx
@@ -0,0 +1,35 @@
+---
+title: Centre Développeur dTax
+description: Moteur de calcul fiscal crypto open-source — 23 parseurs d'exchange, 8 méthodes de coût de base, export Form 8949 / TXF.
+template: splash
+hero:
+ tagline: Calculs fiscaux crypto de niveau professionnel, disponibles en tant que package npm.
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: Commencer
+ link: /fr/introduction/
+ icon: right-arrow
+ variant: primary
+ - text: Voir sur GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ Bibliothèque TypeScript sans dépendances. Parsez des CSV, calculez les plus-values, exportez Form 8949 / TXF.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit, et 15 autres.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+ Gratuit pour les projets open-source. Licence commerciale disponible pour les produits SaaS.
+
+
diff --git a/apps/docs-site/src/content/docs/fr/introduction.mdx b/apps/docs-site/src/content/docs/fr/introduction.mdx
new file mode 100644
index 00000000..f22ff195
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: Introduction
+description: Qu'est-ce que dTax et le centre développeur dtax.dev
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# Centre Développeur dTax
+
+**dTax** est une plateforme fiscale crypto open-core. Le moteur de calcul central est sous licence AGPL-3.0 et disponible en tant que package npm — vous pouvez ainsi intégrer des calculs fiscaux crypto de niveau professionnel dans vos propres applications.
+
+## Ce que vous trouverez ici
+
+
+
+ Une bibliothèque TypeScript sans dépendances pour parser des CSV d'exchanges et calculer les plus-values en utilisant n'importe quelle méthode de coût de base.
+
+
+ Une API gérée pour importer des transactions, exécuter des calculs fiscaux et générer des rapports Form 8949 / TXF — sans infrastructure à gérer.
+
+
+ Parseurs intégrés pour Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit, et 15 autres.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+
+## Modèle Open Core
+
+| Couche | Licence | Accès |
+|--------|---------|-------|
+| `@dtax/tax-engine` | AGPL-3.0 | Public sur GitHub + npm |
+| REST API | Commercial | getdtax.com |
+| Application Web | Commercial | getdtax.com |
+
+Si vous utilisez le moteur fiscal dans un produit commercial, vous devez publier vos modifications en open-source (AGPL-3.0) **ou** nous contacter pour obtenir une licence commerciale.
diff --git a/apps/docs-site/src/content/docs/fr/quickstart.mdx b/apps/docs-site/src/content/docs/fr/quickstart.mdx
new file mode 100644
index 00000000..d37fe62e
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: Démarrage Rapide
+description: Installez @dtax/tax-engine et calculez votre première plus-value en 5 minutes
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## Installation
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## Parser un CSV et calculer les plus-values
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## Détection automatique du format
+
+Si vous ne savez pas quel exchange a généré le CSV, omettez l'option `format` :
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`); // e.g. "coinbase"
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Générer le Form 8949
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/fr/resources/csv-format.mdx b/apps/docs-site/src/content/docs/fr/resources/csv-format.mdx
new file mode 100644
index 00000000..361b674a
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/resources/csv-format.mdx
@@ -0,0 +1,46 @@
+---
+title: Format CSV Générique
+description: Comment formater un CSV pour l'importation si votre exchange n'est pas pris en charge
+draft: false
+---
+
+import { Steps } from '@astrojs/starlight/components';
+
+Si votre exchange ne figure pas dans la [liste des parseurs](/fr/tax-engine/parsers), vous pouvez utiliser notre format CSV générique.
+
+## Télécharger le modèle
+
+[Télécharger le modèle CSV](https://getdtax.com/csv-template.csv)
+
+## Référence des colonnes
+
+| Colonne | Requis | Type | Exemple |
+|---------|--------|------|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | enum (voir ci-dessous) | `BUY` |
+| `Sent Amount` | — | décimal | `0.5` |
+| `Sent Currency` | — | ticker | `BTC` |
+| `Sent Value USD` | — | décimal | `25000.00` |
+| `Received Amount` | — | décimal | `10000` |
+| `Received Currency` | — | ticker | `USDC` |
+| `Received Value USD` | — | décimal | `10000.00` |
+| `Fee Amount` | — | décimal | `0.001` |
+| `Fee Currency` | — | ticker | `ETH` |
+| `Fee Value USD` | — | décimal | `2.50` |
+| `Notes` | — | chaîne | `Sold on Uniswap` |
+
+## Types de transactions
+
+| Type | Description |
+|------|-------------|
+| `BUY` | Achat de crypto avec des devises fiat |
+| `SELL` | Vente de crypto contre des devises fiat |
+| `TRADE` | Échange crypto-to-crypto |
+| `TRANSFER_IN` | Réception depuis un autre portefeuille (non imposable) |
+| `TRANSFER_OUT` | Envoi vers un autre portefeuille (non imposable) |
+| `STAKING` | Récompenses de staking reçues |
+| `MINING` | Récompenses de minage |
+| `AIRDROP` | Airdrop reçu |
+| `INCOME` | Autres revenus en crypto |
+| `FEE` | Frais indépendants |
+| `UNKNOWN` | Sera classifié automatiquement par l'IA |
diff --git a/apps/docs-site/src/content/docs/fr/resources/faq.mdx b/apps/docs-site/src/content/docs/fr/resources/faq.mdx
new file mode 100644
index 00000000..914c2d0f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: Foire aux questions
+description: Questions fréquentes sur la synchronisation des transactions dTax, la prise en charge des portefeuilles et les calculs fiscaux
+draft: false
+---
+
+## Pourquoi certains micro-transferts sont-ils absents de mon historique de transactions ?
+
+dTax filtre automatiquement les **transactions de dust attack** — des micro-transferts inférieurs à 1 000 wei (0,000001 ETH, soit environ $0,003) envoyés à votre adresse de portefeuille.
+
+### Qu'est-ce qu'une dust attack ?
+
+Une dust attack consiste pour un acteur malveillant à envoyer une quantité infime de cryptomonnaie (souvent 1 wei = 0,000000001 ETH) à votre portefeuille. L'objectif est de désanonymiser les portefeuilles en traçant les transactions ultérieures. Ces transferts ne sont pas initiés par vous et n'ont aucune incidence fiscale.
+
+### Pourquoi les filtrer ?
+
+| Raison | Détail |
+|--------|--------|
+| **Aucun impact fiscal** | Les montants inférieurs à 1 000 wei valent moins de $0,01 et ne constituent pas des événements imposables |
+| **Ce ne sont pas vos transactions** | Le dust vous est envoyé *sans votre consentement* — vous n'avez jamais contrôlé ni déplacé ces fonds |
+| **Norme du secteur** | CoinTracker, Koinly et autres outils fiscaux crypto filtrent silencieusement les transferts de dust |
+| **Historique plus propre** | Éliminer le spam rend votre historique de transactions plus précis et plus facilement auditable |
+
+### Quel est le seuil ?
+
+Les transferts inférieurs à **1 000 wei** (0,000001 ETH) sont filtrés pour les types de transactions `TRANSFER_IN` et `TRANSFER_OUT`. Tous les autres types (swaps, trades, récompenses de staking, etc.) sont toujours enregistrés quel que soit le montant.
+
+### Cela affecte-t-il mon rapport fiscal ?
+
+Non. L'IRS n'exige pas de déclarer les dust attacks — vous n'avez pas acquis ces actifs intentionnellement et leur valeur est négligeable. Le filtrage n'a aucun effet sur votre formulaire 8949 ni sur vos calculs de plus-values.
+
+---
+
+## Pourquoi l'enrichissement des prix affiche-t-il un nombre partiel (ex. « 9 / 50 ») ?
+
+Le compteur d'enrichissement des prix ne comprend que les **transactions imposables** (BUY, SELL, TRADE, DEX_SWAP, STAKING_REWARD, etc.). Les simples transferts entre vos propres portefeuilles (`TRANSFER_IN` / `TRANSFER_OUT`) sont exclus car ils ne sont pas des événements imposables et ne nécessitent pas de prix en USD pour la déclaration fiscale.
+
+---
+
+## Pourquoi la synchronisation de mon portefeuille prend-elle autant de temps ?
+
+La synchronisation d'un portefeuille EVM interroge jusqu'à 5 réseaux blockchain (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism) de manière séquentielle pour respecter la limite de débit du plan gratuit d'Etherscan (5 requêtes/seconde). Chaque chaîne effectue 5 appels API en parallèle. Une synchronisation complète sur toutes les chaînes peut prendre 30 à 60 secondes.
+
+---
+
+## Pourquoi mon calcul fiscal affiche-t-il $0 pour les transactions de portefeuille ?
+
+Si votre portefeuille ne contient que des transactions `TRANSFER_IN` et `TRANSFER_OUT`, le total fiscal sera $0. Les transferts entre vos propres portefeuilles ne sont **pas des événements imposables** — aucune plus-value ou moins-value n'est réalisée tant que vous ne vendez pas, n'échangez pas ou n'utilisez pas l'actif.
diff --git a/apps/docs-site/src/content/docs/fr/resources/license.mdx b/apps/docs-site/src/content/docs/fr/resources/license.mdx
new file mode 100644
index 00000000..523171b1
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/resources/license.mdx
@@ -0,0 +1,39 @@
+---
+title: Licence Open Core
+description: Modèle open core AGPL-3.0 — ce que vous pouvez et ne pouvez pas faire
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+Le package npm `@dtax/tax-engine` est sous licence **GNU Affero General Public License v3.0**.
+
+### Vous POUVEZ
+
+- L'utiliser dans des projets personnels gratuitement
+- Étudier et modifier le code source
+- Distribuer des versions modifiées (doit rester sous AGPL-3.0)
+- L'utiliser en interne sans le publier en open-source (usage interne uniquement)
+
+### Vous DEVEZ (en cas de distribution)
+
+- Inclure le texte complet de la licence AGPL-3.0
+- Publier toutes les modifications en open-source sous AGPL-3.0
+- Fournir l'accès au code source aux utilisateurs de votre service
+
+### Vous AVEZ BESOIN d'une Licence Commerciale si
+
+- Vous créez un produit SaaS utilisant le moteur sans le publier en open-source
+- Vous souhaitez conserver vos modifications de manière propriétaire
+
+## Licence Commerciale
+
+Contactez [hello@getdtax.com](mailto:hello@getdtax.com) pour les options de licence commerciale.
+
+## Application Web & API
+
+L'application web dTax et l'API REST sont des logiciels propriétaires sous la **dTax Commercial License**. Ils ne sont pas open-source.
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/fr/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/fr/resources/self-hosting.mdx
new file mode 100644
index 00000000..65fc90f0
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/resources/self-hosting.mdx
@@ -0,0 +1,202 @@
+---
+title: Auto-hébergement
+description: Déployer dTax sur votre propre serveur avec Docker Compose — stack complet avec PostgreSQL, Redis, API et Web
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Déployez dTax sur votre serveur Linux en moins de 15 minutes avec Docker Compose.
+
+## Prérequis
+
+- Serveur Linux (Ubuntu 22.04+ recommandé), 2+ Go de RAM
+- Docker Engine 24+ et Docker Compose v2
+- Un nom de domaine pointant vers l'IP du serveur
+- Ports 80 et 443 ouverts dans le pare-feu
+
+## Démarrage rapide
+
+
+
+1. **Cloner le dépôt**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **Configurer les variables d'environnement**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ Éditez `.env` et renseignez toutes les valeurs requises :
+
+ | Variable | Description |
+ | -------- | ----------- |
+ | `POSTGRES_PASSWORD` | Mot de passe de base de données robuste |
+ | `JWT_SECRET` | Chaîne aléatoire, 32 caractères minimum |
+ | `ENCRYPTION_KEY` | **Chaîne hexadécimale de 64 caractères** — voir note ci-dessous |
+ | `CORS_ORIGIN` | Votre domaine, ex. `https://tax.example.com` |
+ | `APP_URL` | Même domaine (utilisé dans les emails de réinitialisation) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api` (**variable compilée** — doit être définie avant `docker compose build`) |
+
+
+ La clé de chiffrement **doit** être une chaîne hexadécimale de 64 caractères (32 octets bruts). Tout autre format provoque un crash de l'API au démarrage.
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **Démarrer les services**
+
+ ```bash
+ docker compose up -d
+ ```
+
+ Lance PostgreSQL, Redis, API, Web et nginx. Le service `migrate` exécute automatiquement les migrations de base de données.
+
+ Vérifier le bon fonctionnement :
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## Architecture
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ Routage │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS avec Let's Encrypt
+
+
+
+1. **Mettre à jour la configuration nginx**
+
+ Éditez `docker/nginx/nginx.conf` et remplacez `server_name _;` par votre domaine :
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **Obtenir le certificat**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **Activer HTTPS et redémarrer nginx**
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **Renouvellement automatique des certificats**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## Premier administrateur
+
+1. Créez un compte sur `https://yourdomain.com/register`
+2. Promouvez le compte en administrateur via la base de données :
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## Mises à jour
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+## Sauvegardes
+
+```bash
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# Sauvegarde automatique chaque jour à 2h
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# Restaurer depuis une sauvegarde
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## Services optionnels
+
+| Service | Variables d'environnement | Rôle |
+| ------- | ------------------------- | ---- |
+| Resend | `RESEND_API_KEY`, `FROM_EMAIL` | Vérification email & réinitialisation mot de passe (sans cela, impossible de réinitialiser les mots de passe) |
+| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`, `STRIPE_CPA_PRICE_ID` | Facturation des abonnements |
+| Anthropic | `ANTHROPIC_API_KEY` | Classification IA des transactions & chat |
+| Etherscan | `ETHERSCAN_API_KEY` | Indexation blockchain EVM |
+| Solscan | `SOLSCAN_API_KEY` | Indexation blockchain Solana |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` | Analytics produit |
+| Sentry | `SENTRY_DSN` | Suivi des erreurs |
+
+## Dépannage
+
+**Les services ne démarrent pas**
+
+```bash
+docker compose logs api
+docker compose logs web
+docker compose logs nginx
+```
+
+**L'API crashe immédiatement**
+
+Cherchez `FATAL: ENCRYPTION_KEY` dans les logs API. Régénérez la clé avec `openssl rand -hex 32`.
+
+**Tout réinitialiser**
+
+
+Supprime toutes les données, y compris la base de données. Effectuez d'abord une sauvegarde.
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/fr/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/fr/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..e3b16713
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/tax-engine/cost-basis.mdx
@@ -0,0 +1,52 @@
+---
+title: Méthodes de Coût de Base
+description: FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling
+draft: false
+---
+
+## Méthodes prises en charge
+
+| Méthode | ID | Conforme IRS | Notes |
+|---------|----|--------------|-------|
+| First In, First Out | `FIFO` | ✅ Par défaut | Les lots les plus anciens vendus en premier |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Doit choisir Specific ID |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Doit choisir Specific ID |
+| Specific ID | `SPECIFIC_ID` | ✅ | Sélection manuelle des lots |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG, détention 1 an |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | Coût de base moyen |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 pool + règle des 30 jours |
+
+## Note IRS
+
+L'IRS autorise **FIFO** et **Specific Identification** pour les cryptos (Rev. Rul. 2023-14). LIFO et HIFO sont techniquement des stratégies Specific ID — vous devez tenir des registres par lot et appliquer votre méthode de manière cohérente.
+
+## Utilisation
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+// Single method
+const result = computeGains(transactions, {
+ method: 'FIFO',
+ taxYear: 2024,
+});
+
+// Compare all 7 comparable methods (excludes SPECIFIC_ID)
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## Structure du résultat
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/fr/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/fr/tax-engine/overview.mdx
new file mode 100644
index 00000000..98ade574
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/tax-engine/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: Aperçu du Moteur Fiscal
+description: '@dtax/tax-engine — le moteur de calcul central'
+draft: false
+---
+
+`@dtax/tax-engine` est une bibliothèque TypeScript-first sans dépendances pour le calcul fiscal des cryptomonnaies.
+
+## Fonctionnalités
+
+- **23 parseurs d'exchange** — détection automatique ou spécification manuelle du format
+- **8 méthodes de coût de base** — FIFO, LIFO, HIFO, Specific ID, et plus encore
+- **Types de transactions** — Achat, Vente, Échange, Staking, Minage, Airdrop, NFT, DeFi, Frais
+- **Génération de rapports** — Form 8949 (CSV/PDF/TXF), résumé Schedule D
+- **Détection des wash sales** — signale les violations de la règle de rachat à 30 jours
+- **Déduplication** — détection des doublons par empreinte de contenu
+
+## Fonctions principales
+
+| Fonction | Description |
+|----------|-------------|
+| `parseCsv(csv, options?)` | Parser un CSV d'exchange en transactions normalisées |
+| `computeGains(txs, options)` | Calculer les plus-values pour une année fiscale |
+| `compareAllMethods(txs, year)` | Comparer les gains entre les 7 méthodes comparables |
+| `generateForm8949Csv(disposals, options)` | Exporter le Form 8949 en CSV |
+| `generateTxfFile(disposals, options)` | Exporter un fichier TXF pour les logiciels fiscaux |
+
+## Types TypeScript
+
+```typescript
+type CsvFormat =
+ | 'coinbase' | 'binance' | 'binance_us' | 'kraken' | 'gemini'
+ | 'crypto_com' | 'kucoin' | 'okx' | 'bybit' | 'gate' | 'bitget'
+ | 'mexc' | 'htx' | 'etherscan' | 'etherscan_erc20'
+ | 'solscan' | 'solscan_defi' | 'bitfinex' | 'poloniex'
+ | 'koinly' | 'cointracker' | 'cryptact' | 'generic';
+
+type CostBasisMethod =
+ | 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID'
+ | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string; // ISO 8601
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/fr/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/fr/tax-engine/parsers.mdx
new file mode 100644
index 00000000..dd126d7f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/tax-engine/parsers.mdx
@@ -0,0 +1,83 @@
+---
+title: Parseurs d'Exchange
+description: Formats d'export CSV pris en charge pour 23 exchanges et blockchains
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## Exchanges pris en charge
+
+| Exchange | ID de format | Notes |
+|----------|-------------|-------|
+| Coinbase / Coinbase Pro | `coinbase` | Transactions + fills |
+| Binance International | `binance` | Historique Spot + convert |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | Export du grand livre |
+| Gemini | `gemini` | Historique des transactions |
+| Crypto.com | `crypto_com` | Export de l'application |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## Explorateurs de blockchain
+
+| Source | ID de format | Notes |
+|--------|-------------|-------|
+| Etherscan (Transactions) | `etherscan` | Nécessite `userAddress` + `nativeAsset` |
+| Etherscan (Tokens ERC-20) | `etherscan_erc20` | Nécessite `userAddress` |
+| Solscan (Transferts SOL) | `solscan` | Nécessite `userAddress` |
+| Solscan (DeFi) | `solscan_defi` | |
+
+## Outils d'importation
+
+| Outil | ID de format |
+|-------|-------------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| CSV Générique | `generic` |
+
+## Utilisation
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+// Specific format
+const result = parseCsv(csv, { format: 'kraken' });
+
+// Etherscan with wallet address
+const result = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH', // or 'BNB', 'MATIC', 'AVAX', 'FTM'
+});
+
+// Auto-detect
+const result = parseCsv(csv);
+console.log(result.summary.format); // detected format
+```
+
+## Format CSV générique
+
+Si votre exchange n'est pas listé, utilisez le format `generic`. Votre CSV doit comporter ces colonnes :
+
+| Colonne | Requis | Description |
+|---------|--------|-------------|
+| `Date` | ✅ | ISO 8601 ou MM/DD/YYYY |
+| `Type` | ✅ | BUY, SELL, TRADE, etc. |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[Télécharger le modèle CSV](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/fr/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/fr/tax-engine/reports.mdx
new file mode 100644
index 00000000..860b1abc
--- /dev/null
+++ b/apps/docs-site/src/content/docs/fr/tax-engine/reports.mdx
@@ -0,0 +1,34 @@
+---
+title: Génération de Rapports
+description: Génération de rapports Form 8949, Schedule D, TXF et PDF
+draft: false
+---
+
+## Form 8949 (CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+// Returns RFC 4180 CSV string ready to import into tax software
+```
+
+## Export TXF
+
+TXF (Tax Exchange Format) est pris en charge par TurboTax, H&R Block et TaxAct :
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+// Returns TXF string — save as .txf and import into your tax software
+```
+
+## Résumé Schedule D
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/ja/api/authentication.mdx b/apps/docs-site/src/content/docs/ja/api/authentication.mdx
new file mode 100644
index 00000000..679c0910
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/api/authentication.mdx
@@ -0,0 +1,37 @@
+---
+title: 認証
+description: dTax REST API への認証方法
+draft: false
+---
+
+dTax API は認証に **HttpOnly セッションクッキー** を使用します。これにより XSS によるトークン盗難を防ぎます。
+
+## サインアップ / ログイン
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register -H "Content-Type: application/json" -d '{"email":"you@example.com","password":"yourpassword"}' -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login -H "Content-Type: application/json" -d '{"email":"you@example.com","password":"yourpassword"}' -c cookies.txt
+```
+
+レスポンスには、7日間有効な `session` HttpOnly クッキーが設定されます。
+
+## クッキーの使用方法
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions -b cookies.txt
+```
+
+## OAuth
+
+Google および GitHub による OAuth 認証もサポートしています:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+認証成功後、どちらも `getdtax.com/auth/callback` にリダイレクトされます。
diff --git a/apps/docs-site/src/content/docs/ja/api/overview.mdx b/apps/docs-site/src/content/docs/ja/api/overview.mdx
new file mode 100644
index 00000000..6b0ba0d8
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/api/overview.mdx
@@ -0,0 +1,46 @@
+---
+title: REST API 概要
+description: dTax マネージド REST API — 取引のインポート、ゲインの計算、レポートのダウンロード
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+dTax REST API は **`https://getdtax.com/api/v1`** で提供されるマネージドサービスです。ストレージ、計算処理、レポート生成をすべて担うため、状態管理を自前で行う必要はありません。
+
+## ベース URL
+
+```
+https://getdtax.com/api/v1
+```
+
+## 認証
+
+すべてのエンドポイントは `/auth/login` で取得したセッションクッキーが必要です。詳細は [認証](/api/authentication) を参照してください。
+
+## 主要エンドポイント
+
+| エンドポイント | 説明 |
+|--------------|------|
+| `POST /transactions/import` | CSV をアップロードし、自動解析・重複排除・保存を行う |
+| `GET /transactions` | フィルター付きでユーザーの取引一覧を取得する |
+| `GET /tax/summary` | 課税年度のキャピタルゲインサマリーを取得する |
+| `POST /tax/calculate` | 完全なゲイン計算を実行する |
+| `GET /tax/reports/:id/download` | Form 8949 / TXF / PDF をダウンロードする |
+| `GET /notifications` | ユーザーの通知フィードを取得する |
+
+## OpenAPI 仕様
+
+
+
+## レート制限
+
+| プラン | 制限 |
+|--------|------|
+| FREE | 取引 50件、AI メッセージ 5件/日 |
+| PRO ($49/月) | 無制限 |
+| CPA ($499/年) | 無制限 + クライアントアカウント 10件 |
diff --git a/apps/docs-site/src/content/docs/ja/index.mdx b/apps/docs-site/src/content/docs/ja/index.mdx
new file mode 100644
index 00000000..5d00ed52
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/index.mdx
@@ -0,0 +1,35 @@
+---
+title: dTax デベロッパーハブ
+description: オープンソースの仮想通貨税計算エンジン — 23取引所パーサー、8つのコスト基準計算方法、Form 8949 / TXF エクスポート対応。
+template: splash
+hero:
+ tagline: npm パッケージとして利用できる、プロフェッショナルグレードの仮想通貨税計算。
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: はじめる
+ link: introduction
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ 依存関係ゼロの TypeScript ライブラリ。CSV の解析、キャピタルゲインの計算、Form 8949 / TXF のエクスポートに対応。
+
+
+ Coinbase、Binance、Kraken、Gemini、Etherscan、Solscan、OKX、Bybit、その他 15 取引所に対応。
+
+
+ FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling。
+
+
+ オープンソースプロジェクトは無料で利用可能。SaaS 製品向けの商用ライセンスもあります。
+
+
diff --git a/apps/docs-site/src/content/docs/ja/introduction.mdx b/apps/docs-site/src/content/docs/ja/introduction.mdx
new file mode 100644
index 00000000..f377e813
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: はじめに
+description: dTax とは何か、そして dtax.dev デベロッパーハブについて
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# dTax デベロッパーハブ
+
+**dTax** はオープンコアの仮想通貨税計算プラットフォームです。コア計算エンジンは AGPL-3.0 ライセンスのもと npm パッケージとして公開されており、プロフェッショナルグレードの仮想通貨税計算を自分のアプリケーションに組み込むことができます。
+
+## このハブでできること
+
+
+
+ 取引所の CSV を解析し、任意のコスト基準計算方法でキャピタルゲインを計算する、依存関係ゼロの TypeScript ライブラリ。
+
+
+ 取引のインポート、税務計算の実行、Form 8949 / TXF レポートの生成を行うマネージド API。インフラ管理不要。
+
+
+ Coinbase、Binance、Kraken、Gemini、Etherscan、Solscan、OKX、Bybit、その他 15 取引所向けの組み込みパーサー。
+
+
+ FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling。
+
+
+
+## オープンコアモデル
+
+| レイヤー | ライセンス | アクセス |
+|---------|-----------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | GitHub + npm で公開 |
+| REST API | 商用 | getdtax.com |
+| Web アプリ | 商用 | getdtax.com |
+
+商用製品で税計算エンジンを使用する場合は、変更内容をオープンソース化(AGPL-3.0)するか、**または**商用ライセンスについてお問い合わせください。
diff --git a/apps/docs-site/src/content/docs/ja/quickstart.mdx b/apps/docs-site/src/content/docs/ja/quickstart.mdx
new file mode 100644
index 00000000..ce070b59
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: クイックスタート
+description: '@dtax/tax-engine をインストールして、5分で最初のキャピタルゲインを計算する'
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## インストール
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## CSV を解析してゲインを計算する
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## フォーマットの自動検出
+
+CSV を生成した取引所が不明な場合は、`format` オプションを省略してください:
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`);
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Form 8949 の生成
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/ja/resources/csv-format.mdx b/apps/docs-site/src/content/docs/ja/resources/csv-format.mdx
new file mode 100644
index 00000000..0f479dec
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/resources/csv-format.mdx
@@ -0,0 +1,44 @@
+---
+title: 汎用 CSV フォーマット
+description: 対応取引所以外の CSV をインポートする際のフォーマット方法
+draft: false
+---
+
+ご利用の取引所が [パーサー一覧](/tax-engine/parsers) に含まれていない場合は、汎用 CSV フォーマットをご利用ください。
+
+## テンプレートのダウンロード
+
+[CSV テンプレートをダウンロード](https://getdtax.com/csv-template.csv)
+
+## カラムリファレンス
+
+| カラム | 必須 | 型 | 例 |
+|--------|------|----|----|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | enum | `BUY` |
+| `Sent Amount` | — | 小数 | `0.5` |
+| `Sent Currency` | — | ティッカー | `BTC` |
+| `Sent Value USD` | — | 小数 | `25000.00` |
+| `Received Amount` | — | 小数 | `10000` |
+| `Received Currency` | — | ティッカー | `USDC` |
+| `Received Value USD` | — | 小数 | `10000.00` |
+| `Fee Amount` | — | 小数 | `0.001` |
+| `Fee Currency` | — | ティッカー | `ETH` |
+| `Fee Value USD` | — | 小数 | `2.50` |
+| `Notes` | — | 文字列 | `Sold on Uniswap` |
+
+## トランザクションタイプ
+
+| タイプ | 説明 |
+|--------|------|
+| `BUY` | 法定通貨で仮想通貨を購入 |
+| `SELL` | 仮想通貨を法定通貨で売却 |
+| `TRADE` | 仮想通貨同士のスワップ |
+| `TRANSFER_IN` | 別ウォレットからの受け取り(課税対象外) |
+| `TRANSFER_OUT` | 別ウォレットへの送付(課税対象外) |
+| `STAKING` | ステーキング報酬の受け取り |
+| `MINING` | マイニング報酬 |
+| `AIRDROP` | エアドロップの受け取り |
+| `INCOME` | その他の仮想通貨収入 |
+| `FEE` | 単独の手数料 |
+| `UNKNOWN` | AI による自動分類 |
diff --git a/apps/docs-site/src/content/docs/ja/resources/faq.mdx b/apps/docs-site/src/content/docs/ja/resources/faq.mdx
new file mode 100644
index 00000000..2091fb25
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: よくある質問
+description: dTax のトランザクション同期、ウォレット対応、税務計算に関するよくある質問
+draft: false
+---
+
+## なぜ一部の少額送金がトランザクション履歴に表示されないのですか?
+
+dTax は**ダスト攻撃トランザクション**(1,000 wei 未満、つまり 0.000001 ETH ≈ $0.003 以下の微小送金)を自動的にフィルタリングします。
+
+### ダスト攻撃とは?
+
+ダスト攻撃とは、悪意のある第三者があなたのウォレットアドレスに極めて少量の仮想通貨(多くの場合 1 wei = 0.000000001 ETH)を送りつける行為です。目的はその後の取引を追跡してウォレットの匿名性を解除することです。これらはあなたが開始した送金ではなく、税務上の影響もありません。
+
+### なぜフィルタリングするのですか?
+
+| 理由 | 詳細 |
+|------|------|
+| **税務上の影響ゼロ** | 1,000 wei 未満の金額は $0.01 以下であり、課税対象のイベントにはなりません |
+| **自分の取引ではない** | ダストはあなたの同意なく*送りつけられた*ものです。その資金を管理・移動したわけではありません |
+| **業界標準** | CoinTracker、Koinly などの主要な仮想通貨税務ツールも同様にダスト送金を静かにフィルタリングしています |
+| **記録の精度向上** | スパムを除去することで、トランザクション履歴がより正確で監査しやすくなります |
+
+### フィルタリングの閾値は?
+
+`TRANSFER_IN` および `TRANSFER_OUT` タイプのトランザクションに対し、**1,000 wei**(0.000001 ETH)未満の送金はフィルタリングされます。その他のトランザクションタイプ(スワップ、取引、ステーキング報酬など)は金額にかかわらず常に記録されます。
+
+### 税務レポートに影響しますか?
+
+いいえ。IRS はダスト攻撃の申告を求めていません。これらの資産は意図的に取得したものではなく、その価値は無視できます。フィルタリングは Form 8949 やキャピタルゲイン計算に影響しません。
+
+---
+
+## 価格補完が部分的な件数(例:「9 / 50」)を表示するのはなぜですか?
+
+価格補完の件数には**課税対象取引**(BUY、SELL、TRADE、DEX_SWAP、STAKING_REWARD など)のみが含まれます。自分のウォレット間の単純な送金(`TRANSFER_IN` / `TRANSFER_OUT`)は課税対象イベントではなく、税務申告に USD 価格が不要なため除外されます。
+
+---
+
+## ウォレット同期に時間がかかるのはなぜですか?
+
+EVM ウォレットの同期は、Etherscan の無料プランの制限(5 リクエスト/秒)を超えないよう、最大 5 つのブロックチェーンネットワーク(Ethereum、Polygon、BNB Chain、Arbitrum、Optimism)を順番にクエリします。各チェーンは 5 つの API 呼び出しを並行して実行します。全チェーンの完全同期には 30〜60 秒かかる場合があります。
+
+---
+
+## ウォレット取引の税務計算がすべて $0 になるのはなぜですか?
+
+ウォレットに `TRANSFER_IN` と `TRANSFER_OUT` のトランザクションしかない場合、税額合計は $0 になります。自分のウォレット間の送金は**課税対象イベントではありません**。資産を売却、交換、または使用するまで、キャピタルゲインや損失は発生しません。
diff --git a/apps/docs-site/src/content/docs/ja/resources/license.mdx b/apps/docs-site/src/content/docs/ja/resources/license.mdx
new file mode 100644
index 00000000..181d4414
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/resources/license.mdx
@@ -0,0 +1,36 @@
+---
+title: オープンコアライセンス
+description: AGPL-3.0 オープンコアモデル — できること・できないこと
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+`@dtax/tax-engine` npm パッケージは **GNU Affero General Public License v3.0** のもとでライセンスされています。
+
+### できること
+- 個人プロジェクトへの無料利用
+- ソースコードの閲覧と改変
+- 改変版の配布(AGPL-3.0 を維持する必要があります)
+- 内部利用のみであればオープンソース化不要
+
+### 配布する場合に必要なこと
+- AGPL-3.0 ライセンス全文の同梱
+- すべての変更内容を AGPL-3.0 でオープンソース化
+- サービス利用者へのソースコードアクセスの提供
+
+### 商用ライセンスが必要な場合
+- エンジンを使用した SaaS 製品を構築し、オープンソース化しない場合
+- 変更内容をプロプライエタリに保ちたい場合
+
+## 商用ライセンス
+
+商用ライセンスのオプションについては [hello@getdtax.com](mailto:hello@getdtax.com) までお問い合わせください。
+
+## Web アプリ & API
+
+dTax の Web アプリケーションおよび REST API は **dTax 商用ライセンス** のもとにあるプロプライエタリソフトウェアです。オープンソースではありません。
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/ja/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/ja/resources/self-hosting.mdx
new file mode 100644
index 00000000..6265558f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/resources/self-hosting.mdx
@@ -0,0 +1,205 @@
+---
+title: セルフホスティング
+description: Docker Compose を使用して自分のサーバーに dTax をデプロイ — PostgreSQL、Redis、API、Web の完全スタック
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Docker Compose を使って Linux サーバーに dTax を 15 分以内でデプロイできます。
+
+## 前提条件
+
+- Linux サーバー(Ubuntu 22.04+ 推奨)、2 GB 以上の RAM
+- Docker Engine 24+ および Docker Compose v2
+- サーバーの IP に向けたドメイン名
+- ファイアウォールでポート 80 と 443 を開放
+
+## クイックスタート
+
+
+
+1. **リポジトリをクローン**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **環境変数を設定**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ `.env` を編集して必須項目をすべて入力してください:
+
+ | 変数 | 説明 |
+ | ---- | ---- |
+ | `POSTGRES_PASSWORD` | 強力なデータベースパスワード |
+ | `JWT_SECRET` | ランダムな文字列(32 文字以上) |
+ | `ENCRYPTION_KEY` | **64 文字の 16 進数文字列** — 下記の注意事項を参照 |
+ | `CORS_ORIGIN` | ドメイン名(例: `https://tax.example.com`) |
+ | `APP_URL` | 同じドメイン(パスワードリセットメールのリンクに使用) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api`(**ビルド時変数** — `docker compose build` 実行前に設定必須) |
+
+
+ 暗号化キーは **64 文字の 16 進数文字列**(32 バイト)でなければなりません。他の形式の場合、API は起動時にクラッシュします。
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **サービスを起動**
+
+ ```bash
+ docker compose up -d
+ ```
+
+ PostgreSQL、Redis、API、Web、nginx が起動します。`migrate` サービスがデータベースマイグレーションを自動実行します。
+
+ 動作確認:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## アーキテクチャ
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ ルーティング │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS 証明書(Let's Encrypt)
+
+
+
+1. **nginx 設定を更新**
+
+ `docker/nginx/nginx.conf` を編集して `server_name _;` をドメインに変更:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **証明書を取得**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **HTTPS を有効化**
+
+ `docker/nginx/nginx.conf` に HTTPS サーバーブロックを追加後、nginx を再起動:
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **証明書の自動更新**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## 最初の管理者ユーザー
+
+1. `https://yourdomain.com/register` でアカウントを登録
+2. データベースで管理者に昇格:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## アップデート
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+## バックアップ
+
+```bash
+# バックアップ実行
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# 毎日午前 2 時に自動バックアップ
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# バックアップから復元
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## オプションサービス
+
+| サービス | 環境変数 | 用途 |
+| -------- | -------- | ---- |
+| Resend | `RESEND_API_KEY`、`FROM_EMAIL` | メール認証・パスワードリセット(未設定の場合パスワードリセット不可) |
+| Stripe | `STRIPE_SECRET_KEY`、`STRIPE_WEBHOOK_SECRET`、`STRIPE_PRO_PRICE_ID`、`STRIPE_CPA_PRICE_ID` | サブスクリプション課金 |
+| Anthropic | `ANTHROPIC_API_KEY` | AI トランザクション分類・チャット |
+| Etherscan | `ETHERSCAN_API_KEY` | EVM ブロックチェーンインデックス |
+| Solscan | `SOLSCAN_API_KEY` | Solana ブロックチェーンインデックス |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`、`NEXT_PUBLIC_POSTHOG_HOST` | プロダクト分析 |
+| Sentry | `SENTRY_DSN` | エラートラッキング |
+
+## トラブルシューティング
+
+**サービスが起動しない**
+
+```bash
+docker compose logs api
+docker compose logs web
+docker compose logs nginx
+```
+
+**API が即座にクラッシュする**
+
+API ログで `FATAL: ENCRYPTION_KEY` を確認してください。`ENCRYPTION_KEY` が有効な 64 文字の 16 進数文字列でないことを示しています。`openssl rand -hex 32` で再生成してください。
+
+**すべてをリセット**
+
+
+データベースを含むすべてのデータが削除されます。事前にバックアップを取ってください。
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/ja/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/ja/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..5b786d40
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/tax-engine/cost-basis.mdx
@@ -0,0 +1,47 @@
+---
+title: コスト基準計算方法
+description: FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling
+draft: false
+---
+
+## 対応メソッド
+
+| メソッド | ID | IRS 準拠 | 備考 |
+|---------|----|---------|----|
+| First In, First Out | `FIFO` | ✅ デフォルト | 最も古いロットから売却 |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Specific ID を選択する必要あり |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Specific ID を選択する必要あり |
+| Specific ID | `SPECIFIC_ID` | ✅ | ロットの手動選択 |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG、1年保有 |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | 平均コスト基準 |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 プール + 30日ルール |
+
+## IRS に関する注記
+
+IRS は仮想通貨に対して **FIFO** と **Specific Identification** を認めています(Rev. Rul. 2023-14)。LIFO と HIFO は技術的には Specific ID 戦略であり、ロットレベルの記録を維持し、選択した方法を一貫して適用する必要があります。
+
+## 使用方法(コードブロック — 翻訳しない)
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## 結果の型
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/ja/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/ja/tax-engine/overview.mdx
new file mode 100644
index 00000000..81eeadf0
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/tax-engine/overview.mdx
@@ -0,0 +1,44 @@
+---
+title: 税計算エンジン概要
+description: '@dtax/tax-engine — コア計算エンジン'
+draft: false
+---
+
+`@dtax/tax-engine` は仮想通貨税計算のための TypeScript ファースト・依存関係ゼロのライブラリです。
+
+## 機能
+
+- **23 の取引所パーサー** — フォーマットの自動検出または手動指定
+- **8 つのコスト基準計算方法** — FIFO、LIFO、HIFO、Specific ID など
+- **トランザクションタイプ** — Buy、Sell、Trade、Staking、Mining、Airdrop、NFT、DeFi、Fees
+- **レポート生成** — Form 8949(CSV/PDF/TXF)、Schedule D サマリー
+- **Wash Sale 検出** — 30日の再購入ルール違反をフラグ
+- **重複排除** — コンテンツフィンガープリントによる重複検出
+
+## コア関数
+
+| 関数 | 説明 |
+|------|------|
+| `parseCsv(csv, options?)` | 取引所の CSV を正規化されたトランザクションに解析する |
+| `computeGains(txs, options)` | 課税年度のキャピタルゲインを計算する |
+| `compareAllMethods(txs, year)` | 7つの比較可能なメソッド全体でゲインを比較する |
+| `generateForm8949Csv(disposals, options)` | Form 8949 を CSV としてエクスポートする |
+| `generateTxfFile(disposals, options)` | 税務ソフトウェア向けに TXF ファイルをエクスポートする |
+
+## TypeScript 型(コードは翻訳しない)
+
+```typescript
+type CsvFormat = 'coinbase' | 'binance' | 'kraken' | 'gemini' | 'etherscan' | 'generic' /* ... */;
+type CostBasisMethod = 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID' | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string;
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/ja/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/ja/tax-engine/parsers.mdx
new file mode 100644
index 00000000..c0a7034c
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/tax-engine/parsers.mdx
@@ -0,0 +1,78 @@
+---
+title: 取引所パーサー
+description: 23 の取引所・ブロックチェーンに対応した CSV エクスポートフォーマット
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## 対応取引所
+
+| 取引所 | フォーマット ID | 備考 |
+|--------|--------------|------|
+| Coinbase / Coinbase Pro | `coinbase` | トランザクション + 約定履歴 |
+| Binance International | `binance` | スポット + コンバート履歴 |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | 台帳エクスポート |
+| Gemini | `gemini` | 取引履歴 |
+| Crypto.com | `crypto_com` | アプリエクスポート |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## ブロックチェーンエクスプローラー
+
+| ソース | フォーマット ID | 備考 |
+|--------|--------------|------|
+| Etherscan(トランザクション) | `etherscan` | `userAddress` + `nativeAsset` が必要 |
+| Etherscan(ERC-20 トークン) | `etherscan_erc20` | `userAddress` が必要 |
+| Solscan(SOL 送金) | `solscan` | `userAddress` が必要 |
+| Solscan(DeFi) | `solscan_defi` | |
+
+## インポートツール
+
+| ツール | フォーマット ID |
+|--------|--------------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| Generic CSV | `generic` |
+
+## 使用方法
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+const result = parseCsv(csv, { format: 'kraken' });
+
+const result2 = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH',
+});
+
+const result3 = parseCsv(csv);
+console.log(result3.summary.format);
+```
+
+## 汎用 CSV フォーマット
+
+| カラム | 必須 | 説明 |
+|--------|------|------|
+| `Date` | ✅ | ISO 8601 または MM/DD/YYYY |
+| `Type` | ✅ | BUY、SELL、TRADE など |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[CSV テンプレートをダウンロード](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/ja/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/ja/tax-engine/reports.mdx
new file mode 100644
index 00000000..aeab1dd2
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ja/tax-engine/reports.mdx
@@ -0,0 +1,32 @@
+---
+title: レポート生成
+description: Form 8949、Schedule D、TXF、PDF レポートの生成
+draft: false
+---
+
+## Form 8949(CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+```
+
+## TXF エクスポート
+
+TXF(Tax Exchange Format)は TurboTax、H&R Block、TaxAct に対応しています:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+```
+
+## Schedule D サマリー
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/ko/api/authentication.mdx b/apps/docs-site/src/content/docs/ko/api/authentication.mdx
new file mode 100644
index 00000000..09d515ee
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/api/authentication.mdx
@@ -0,0 +1,33 @@
+---
+title: 인증
+description: dTax REST API 인증 방법
+draft: false
+---
+
+dTax API는 인증에 **HttpOnly 세션 쿠키**를 사용합니다. 이를 통해 XSS 토큰 탈취를 방지합니다.
+
+## 회원가입 / 로그인
+
+```bash
+curl -X POST https://getdtax.com/api/v1/auth/register -H "Content-Type: application/json" -d '{"email":"you@example.com","password":"yourpassword"}' -c cookies.txt
+curl -X POST https://getdtax.com/api/v1/auth/login -H "Content-Type: application/json" -d '{"email":"you@example.com","password":"yourpassword"}' -c cookies.txt
+```
+
+응답으로 7일간 유효한 `session` HttpOnly 쿠키가 설정됩니다.
+
+## 쿠키 사용
+
+```bash
+curl https://getdtax.com/api/v1/transactions -b cookies.txt
+```
+
+## OAuth
+
+Google 및 GitHub OAuth도 지원됩니다:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+성공 시 `getdtax.com/auth/callback`으로 리다이렉트됩니다.
diff --git a/apps/docs-site/src/content/docs/ko/api/overview.mdx b/apps/docs-site/src/content/docs/ko/api/overview.mdx
new file mode 100644
index 00000000..4281069f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/api/overview.mdx
@@ -0,0 +1,42 @@
+---
+title: REST API 개요
+description: dTax 관리형 REST API — 거래 내역 가져오기, 이득 계산, 보고서 다운로드
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+dTax REST API는 **`https://getdtax.com/api/v1`**에서 제공되는 관리형 서비스입니다. 저장, 계산, 보고서 생성을 처리하므로 직접 상태를 관리할 필요가 없습니다.
+
+## 기본 URL
+
+```
+https://getdtax.com/api/v1
+```
+
+## 인증
+
+모든 엔드포인트는 `/auth/login`을 통해 발급된 세션 쿠키가 필요합니다. 자세한 내용은 [인증](/api/authentication)을 참조하세요.
+
+## 주요 엔드포인트
+
+| 엔드포인트 | 설명 |
+|----------|-------------|
+| `POST /transactions/import` | CSV 업로드, 자동 파싱, 중복 제거, 저장 |
+| `GET /transactions` | 필터를 적용한 사용자 거래 목록 조회 |
+| `GET /tax/summary` | 과세 연도별 자본 이득 요약 |
+| `POST /tax/calculate` | 전체 이득 계산 실행 |
+| `GET /tax/reports/:id/download` | Form 8949 / TXF / PDF 다운로드 |
+| `GET /notifications` | 사용자 알림 피드 |
+
+## OpenAPI 명세
+
+
+
+## 요청 제한
+
+| 플랜 | 제한 |
+|------|-------|
+| FREE | 거래 50건, AI 메시지 5건/일 |
+| PRO ($49/월) | 무제한 |
+| CPA ($499/년) | 무제한 + 고객 계정 10개 |
diff --git a/apps/docs-site/src/content/docs/ko/index.mdx b/apps/docs-site/src/content/docs/ko/index.mdx
new file mode 100644
index 00000000..bc25afd6
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/index.mdx
@@ -0,0 +1,35 @@
+---
+title: dTax 개발자 허브
+description: 오픈소스 암호화폐 세금 엔진 — 23개 거래소 파서, 8가지 원가 계산 방법, Form 8949 / TXF 내보내기.
+template: splash
+hero:
+ tagline: npm 패키지로 제공되는 전문가급 암호화폐 세금 계산.
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: 시작하기
+ link: introduction
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ 의존성 없는 TypeScript 라이브러리. CSV 파싱, 자본 이득 계산, Form 8949 / TXF 내보내기.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit 및 15개 이상.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+ 오픈소스 사용은 무료. SaaS 제품용 상업 라이선스도 제공됩니다.
+
+
diff --git a/apps/docs-site/src/content/docs/ko/introduction.mdx b/apps/docs-site/src/content/docs/ko/introduction.mdx
new file mode 100644
index 00000000..d90f3294
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: 소개
+description: dTax와 dtax.dev 개발자 허브에 대한 소개
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# dTax 개발자 허브
+
+**dTax**는 오픈 코어 암호화폐 세금 플랫폼입니다. 핵심 계산 엔진은 AGPL-3.0 라이선스로 npm 패키지로 제공되어, 자체 애플리케이션에 전문가급 암호화폐 세금 계산 기능을 통합할 수 있습니다.
+
+## 제공 내용
+
+
+
+ 거래소 CSV를 파싱하고 원하는 원가 계산 방법으로 자본 이득을 계산하는 의존성 없는 TypeScript 라이브러리.
+
+
+ 거래 내역 가져오기, 세금 계산 실행, Form 8949 / TXF 보고서 생성을 위한 관리형 API — 별도 인프라 불필요.
+
+
+ Coinbase, Binance, Kraken, Gemini, Etherscan, Solscan, OKX, Bybit 및 15개 이상의 내장 파서.
+
+
+ FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling.
+
+
+
+## 오픈 코어 모델
+
+| 레이어 | 라이선스 | 접근 방법 |
+|-------|---------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | GitHub + npm 공개 |
+| REST API | 상업용 | getdtax.com |
+| 웹 앱 | 상업용 | getdtax.com |
+
+세금 엔진을 상업 제품에 사용하는 경우, 변경 사항을 오픈소스로 공개(AGPL-3.0)하거나 **또는** 상업 라이선스 문의를 해주세요.
diff --git a/apps/docs-site/src/content/docs/ko/quickstart.mdx b/apps/docs-site/src/content/docs/ko/quickstart.mdx
new file mode 100644
index 00000000..6490efb2
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/quickstart.mdx
@@ -0,0 +1,56 @@
+---
+title: 빠른 시작
+description: "@dtax/tax-engine 설치 후 5분 안에 첫 자본 이득 계산하기"
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## 설치
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## CSV 파싱 및 이득 계산
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## 형식 자동 감지
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`);
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## Form 8949 생성
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/ko/resources/csv-format.mdx b/apps/docs-site/src/content/docs/ko/resources/csv-format.mdx
new file mode 100644
index 00000000..54bcd3b8
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/resources/csv-format.mdx
@@ -0,0 +1,41 @@
+---
+title: 일반 CSV 형식
+description: 지원되지 않는 거래소의 CSV 가져오기 형식 지정 방법
+draft: false
+---
+
+거래소가 [파서 목록](/tax-engine/parsers)에 없는 경우, 일반 CSV 형식을 사용할 수 있습니다.
+
+## 템플릿 다운로드
+
+[CSV 템플릿 다운로드](https://getdtax.com/csv-template.csv)
+
+## 열 참조
+
+| 열 | 필수 여부 | 타입 | 예시 |
+|--------|----------|------|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | enum | `BUY` |
+| `Sent Amount` | — | decimal | `0.5` |
+| `Sent Currency` | — | ticker | `BTC` |
+| `Received Amount` | — | decimal | `10000` |
+| `Received Currency` | — | ticker | `USDC` |
+| `Fee Amount` | — | decimal | `0.001` |
+| `Fee Currency` | — | ticker | `ETH` |
+| `Notes` | — | string | `Sold on Uniswap` |
+
+## 거래 유형
+
+| 유형 | 설명 |
+|------|-------------|
+| `BUY` | 법정화폐로 암호화폐 구매 |
+| `SELL` | 암호화폐를 법정화폐로 매도 |
+| `TRADE` | 암호화폐 간 교환 |
+| `TRANSFER_IN` | 다른 지갑에서 수신 (비과세) |
+| `TRANSFER_OUT` | 다른 지갑으로 전송 (비과세) |
+| `STAKING` | 스테이킹 보상 수령 |
+| `MINING` | 채굴 보상 |
+| `AIRDROP` | 에어드랍 수령 |
+| `INCOME` | 기타 암호화폐 수입 |
+| `FEE` | 독립 수수료 |
+| `UNKNOWN` | AI가 자동 분류 |
diff --git a/apps/docs-site/src/content/docs/ko/resources/faq.mdx b/apps/docs-site/src/content/docs/ko/resources/faq.mdx
new file mode 100644
index 00000000..acdbb0f6
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: 자주 묻는 질문
+description: dTax 트랜잭션 동기화, 지갑 지원, 세금 계산에 관한 자주 묻는 질문
+draft: false
+---
+
+## 왜 일부 소액 전송이 트랜잭션 내역에 표시되지 않나요?
+
+dTax는 **더스트 공격 트랜잭션**을 자동으로 필터링합니다. 더스트 공격이란 1,000 wei 미만(0.000001 ETH, 약 $0.003)의 극소액을 지갑 주소로 전송하는 행위입니다.
+
+### 더스트 공격이란?
+
+더스트 공격은 악의적인 행위자가 지갑 주소를 추적·식별하기 위해 극소량의 암호화폐(보통 1 wei = 0.000000001 ETH)를 보내는 행위입니다. 이는 사용자가 시작한 전송이 아니며, 세금에도 전혀 영향을 미치지 않습니다.
+
+### 왜 필터링하나요?
+
+| 이유 | 설명 |
+|------|------|
+| **세금 영향 없음** | 1,000 wei 미만은 $0.01 이하로, 과세 이벤트에 해당하지 않습니다 |
+| **내 트랜잭션이 아님** | 더스트는 동의 없이 *보내진* 것으로, 해당 자금을 직접 통제하거나 이동한 적이 없습니다 |
+| **업계 표준** | CoinTracker, Koinly 등 주요 암호화폐 세금 도구도 더스트 전송을 자동으로 필터링합니다 |
+| **깔끔한 기록** | 스팸 제거로 트랜잭션 내역이 더 정확하고 감사하기 쉬워집니다 |
+
+### 필터링 기준값은?
+
+`TRANSFER_IN` 및 `TRANSFER_OUT` 유형에 대해 **1,000 wei**(0.000001 ETH) 미만 전송이 필터링됩니다. 스왑, 거래, 스테이킹 보상 등 다른 모든 트랜잭션 유형은 금액과 관계없이 항상 기록됩니다.
+
+### 세금 보고서에 영향을 미치나요?
+
+아니요. IRS는 더스트 공격 신고를 요구하지 않습니다. 의도적으로 취득한 자산이 아니며 가치도 무시할 수준입니다. 필터링은 Form 8949나 양도소득 계산에 전혀 영향을 주지 않습니다.
+
+---
+
+## 가격 보완이 부분적인 수치(예: "9 / 50")를 표시하는 이유는?
+
+가격 보완 수치에는 **과세 대상 트랜잭션**(BUY, SELL, TRADE, DEX_SWAP, STAKING_REWARD 등)만 포함됩니다. 자신의 지갑 간 단순 전송(`TRANSFER_IN` / `TRANSFER_OUT`)은 과세 이벤트가 아니며 세금 신고 시 USD 가격이 필요하지 않아 제외됩니다.
+
+---
+
+## 지갑 동기화에 시간이 오래 걸리는 이유는?
+
+EVM 지갑 동기화는 Etherscan 무료 플랜의 초당 5개 요청 제한을 지키기 위해 최대 5개 블록체인 네트워크(Ethereum, Polygon, BNB Chain, Arbitrum, Optimism)를 순차적으로 조회합니다. 각 체인에서 5개의 API 호출이 병렬로 실행됩니다. 전체 동기화는 30~60초가 소요될 수 있습니다.
+
+---
+
+## 지갑 트랜잭션의 세금 계산이 모두 $0으로 표시되는 이유는?
+
+지갑에 `TRANSFER_IN`과 `TRANSFER_OUT` 트랜잭션만 있는 경우 세금 합계는 $0입니다. 내 지갑 간 전송은 **과세 이벤트가 아닙니다**. 자산을 매도, 교환 또는 사용할 때까지 양도소득이나 손실이 발생하지 않습니다.
diff --git a/apps/docs-site/src/content/docs/ko/resources/license.mdx b/apps/docs-site/src/content/docs/ko/resources/license.mdx
new file mode 100644
index 00000000..55830e3d
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/resources/license.mdx
@@ -0,0 +1,36 @@
+---
+title: 오픈 코어 라이선스
+description: AGPL-3.0 오픈 코어 모델 — 허용 사항과 금지 사항
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+`@dtax/tax-engine` npm 패키지는 **GNU Affero General Public License v3.0** 라이선스로 제공됩니다.
+
+### 가능한 사항
+- 개인 프로젝트에서 무료로 사용
+- 소스 코드 연구 및 수정
+- 수정된 버전 배포 (AGPL-3.0 유지 필수)
+- 내부적으로 오픈소스 공개 없이 사용
+
+### 배포 시 필수 사항
+- 전체 AGPL-3.0 라이선스 텍스트 포함
+- AGPL-3.0 하에 모든 수정 사항 오픈소스 공개
+- 서비스 사용자에게 소스 코드 접근 제공
+
+### 상업 라이선스가 필요한 경우
+- 엔진을 사용하는 SaaS 제품을 오픈소스 공개 없이 구축하는 경우
+- 수정 사항을 독점적으로 유지하려는 경우
+
+## 상업 라이선스
+
+상업 라이선스 옵션은 [hello@getdtax.com](mailto:hello@getdtax.com)으로 문의해 주세요.
+
+## 웹 앱 및 API
+
+dTax 웹 애플리케이션과 REST API는 **dTax 상업 라이선스** 하의 독점 소프트웨어입니다. 오픈소스가 아닙니다.
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/ko/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/ko/resources/self-hosting.mdx
new file mode 100644
index 00000000..fa514a59
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/resources/self-hosting.mdx
@@ -0,0 +1,202 @@
+---
+title: 셀프 호스팅
+description: Docker Compose를 사용하여 자체 서버에 dTax 배포 — PostgreSQL, Redis, API, Web 전체 스택
+draft: false
+---
+
+import { Steps, Aside } from '@astrojs/starlight/components';
+
+Docker Compose를 사용하여 Linux 서버에 dTax를 15분 내에 배포할 수 있습니다.
+
+## 사전 요구사항
+
+- Linux 서버 (Ubuntu 22.04+ 권장), RAM 2GB 이상
+- Docker Engine 24+ 및 Docker Compose v2
+- 서버 IP로 연결된 도메인 이름
+- 방화벽에서 포트 80 및 443 개방
+
+## 빠른 시작
+
+
+
+1. **저장소 클론**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **환경 변수 설정**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ `.env`를 편집하여 모든 필수 값을 입력하세요:
+
+ | 변수 | 설명 |
+ | ---- | ---- |
+ | `POSTGRES_PASSWORD` | 강력한 데이터베이스 비밀번호 |
+ | `JWT_SECRET` | 무작위 문자열, 32자 이상 |
+ | `ENCRYPTION_KEY` | **64자 16진수 문자열** — 아래 주의사항 참조 |
+ | `CORS_ORIGIN` | 도메인 (예: `https://tax.example.com`) |
+ | `APP_URL` | 동일 도메인 (비밀번호 재설정 이메일 링크에 사용) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api`(**빌드 시간 변수** — `docker compose build` 실행 전에 설정 필수) |
+
+
+ 암호화 키는 **64자 16진수 문자열**(32 바이트)이어야 합니다. 다른 형식을 사용하면 API가 시작 시 크래시됩니다.
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **서비스 시작**
+
+ ```bash
+ docker compose up -d
+ ```
+
+ PostgreSQL, Redis, API, Web, nginx가 시작됩니다. `migrate` 서비스가 데이터베이스 마이그레이션을 자동으로 실행합니다.
+
+ 동작 확인:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## 아키텍처
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ 라우팅 │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS 인증서 (Let's Encrypt)
+
+
+
+1. **nginx 설정 업데이트**
+
+ `docker/nginx/nginx.conf`를 편집하여 `server_name _;`을 도메인으로 교체:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **인증서 발급**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **HTTPS 활성화 후 nginx 재시작**
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **인증서 자동 갱신**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## 첫 번째 관리자 계정
+
+1. `https://yourdomain.com/register`에서 계정 등록
+2. 데이터베이스에서 관리자로 승격:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## 업데이트
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+## 백업
+
+```bash
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# 매일 오전 2시 자동 백업
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# 백업에서 복원
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## 선택적 서비스
+
+| 서비스 | 환경 변수 | 용도 |
+| ------ | --------- | ---- |
+| Resend | `RESEND_API_KEY`, `FROM_EMAIL` | 이메일 인증 및 비밀번호 재설정 (미설정 시 비밀번호 재설정 불가) |
+| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`, `STRIPE_CPA_PRICE_ID` | 구독 결제 |
+| Anthropic | `ANTHROPIC_API_KEY` | AI 트랜잭션 분류 및 채팅 |
+| Etherscan | `ETHERSCAN_API_KEY` | EVM 블록체인 인덱싱 |
+| Solscan | `SOLSCAN_API_KEY` | Solana 블록체인 인덱싱 |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`, `NEXT_PUBLIC_POSTHOG_HOST` | 제품 분석 |
+| Sentry | `SENTRY_DSN` | 오류 추적 |
+
+## 문제 해결
+
+**서비스가 시작되지 않음**
+
+```bash
+docker compose logs api
+docker compose logs web
+docker compose logs nginx
+```
+
+**API가 즉시 크래시**
+
+API 로그에서 `FATAL: ENCRYPTION_KEY`를 확인하세요. `openssl rand -hex 32`로 재생성하세요.
+
+**모든 것 초기화**
+
+
+데이터베이스를 포함한 모든 데이터가 삭제됩니다. 먼저 백업하세요.
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/ko/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/ko/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..478e753d
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/tax-engine/cost-basis.mdx
@@ -0,0 +1,45 @@
+---
+title: 원가 계산 방법
+description: FIFO, LIFO, HIFO, Specific ID, Germany FIFO, PMPA, Total Average, UK Share Pooling
+draft: false
+---
+
+## 지원 방법
+
+| 방법 | ID | IRS 준수 | 비고 |
+|--------|----|---------------|-------|
+| First In, First Out | `FIFO` | ✅ 기본값 | 가장 오래된 로트부터 매도 |
+| Last In, First Out | `LIFO` | ⚠️ Specific ID | Specific ID로 선택 필요 |
+| Highest In, First Out | `HIFO` | ⚠️ Specific ID | Specific ID로 선택 필요 |
+| Specific ID | `SPECIFIC_ID` | ✅ | 수동 로트 선택 |
+| Germany FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG, 1년 보유 |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | Adjusted Cost Base |
+| Total Average | `TOTAL_AVERAGE` | 🌍 | 평균 원가 기준 |
+| UK Share Pooling | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 풀 + 30일 규칙 |
+
+## IRS 참고 사항
+
+IRS는 암호화폐에 대해 **FIFO**와 **Specific Identification**을 허용합니다 (Rev. Rul. 2023-14). LIFO와 HIFO는 기술적으로 Specific ID 전략의 하위 유형입니다.
+
+## 사용법
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## 결과 구조
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/ko/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/ko/tax-engine/overview.mdx
new file mode 100644
index 00000000..bf310da0
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/tax-engine/overview.mdx
@@ -0,0 +1,43 @@
+---
+title: 세금 엔진 개요
+description: '@dtax/tax-engine — 핵심 계산 엔진'
+draft: false
+---
+
+`@dtax/tax-engine`은 암호화폐 세금 계산을 위한 TypeScript 우선, 의존성 없는 라이브러리입니다.
+
+## 기능
+
+- **23개 거래소 파서** — 형식 자동 감지 또는 수동 지정
+- **8가지 원가 계산 방법** — FIFO, LIFO, HIFO, Specific ID 등
+- **거래 유형** — 매수, 매도, 교환, 스테이킹, 채굴, 에어드랍, NFT, DeFi, 수수료
+- **보고서 생성** — Form 8949 (CSV/PDF/TXF), Schedule D 요약
+- **Wash sale 감지** — 30일 재매수 규칙 위반 플래그
+- **중복 제거** — 콘텐츠 지문 기반 중복 감지
+
+## 핵심 함수
+
+| 함수 | 설명 |
+|----------|-------------|
+| `parseCsv(csv, options?)` | 거래소 CSV를 정규화된 거래 내역으로 파싱 |
+| `computeGains(txs, options)` | 과세 연도의 자본 이득 계산 |
+| `compareAllMethods(txs, year)` | 비교 가능한 7가지 방법 간 이득 비교 |
+| `generateForm8949Csv(disposals, options)` | Form 8949를 CSV로 내보내기 |
+| `generateTxfFile(disposals, options)` | 세금 소프트웨어용 TXF 파일 내보내기 |
+
+## TypeScript 타입
+
+```typescript
+type CostBasisMethod = 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID' | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string;
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/ko/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/ko/tax-engine/parsers.mdx
new file mode 100644
index 00000000..86a82a5c
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/tax-engine/parsers.mdx
@@ -0,0 +1,55 @@
+---
+title: 거래소 파서
+description: 23개 거래소 및 블록체인의 지원 CSV 내보내기 형식
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## 지원 거래소
+
+| 거래소 | 형식 ID | 비고 |
+|----------|-----------|-------|
+| Coinbase / Coinbase Pro | `coinbase` | 거래 내역 + 체결 내역 |
+| Binance International | `binance` | 현물 + 전환 내역 |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | 원장 내보내기 |
+| Gemini | `gemini` | 거래 내역 |
+| Crypto.com | `crypto_com` | 앱 내보내기 |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX (Huobi) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## 블록체인 탐색기
+
+| 소스 | 형식 ID | 비고 |
+|--------|-----------|-------|
+| Etherscan (트랜잭션) | `etherscan` | `userAddress` + `nativeAsset` 필요 |
+| Etherscan (ERC-20 토큰) | `etherscan_erc20` | `userAddress` 필요 |
+| Solscan (SOL 전송) | `solscan` | `userAddress` 필요 |
+| Solscan (DeFi) | `solscan_defi` | |
+
+## 가져오기 도구
+
+| 도구 | 형식 ID |
+|------|-----------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| 일반 CSV | `generic` |
+
+## 사용법
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+const result = parseCsv(csv, { format: 'kraken' });
+const result2 = parseCsv(csv, { format: 'etherscan', userAddress: '0xYourWalletAddress', nativeAsset: 'ETH' });
+const result3 = parseCsv(csv);
+console.log(result3.summary.format);
+```
diff --git a/apps/docs-site/src/content/docs/ko/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/ko/tax-engine/reports.mdx
new file mode 100644
index 00000000..3a936c68
--- /dev/null
+++ b/apps/docs-site/src/content/docs/ko/tax-engine/reports.mdx
@@ -0,0 +1,30 @@
+---
+title: 보고서 생성
+description: Form 8949, Schedule D, TXF, PDF 보고서 생성
+draft: false
+---
+
+## Form 8949 (CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+```
+
+## TXF 내보내기
+
+TXF (Tax Exchange Format)는 TurboTax, H&R Block, TaxAct에서 지원됩니다:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+```
+
+## Schedule D 요약
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/content/docs/zh-CN/api/authentication.mdx b/apps/docs-site/src/content/docs/zh-CN/api/authentication.mdx
new file mode 100644
index 00000000..29e5d97f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/api/authentication.mdx
@@ -0,0 +1,44 @@
+---
+title: 身份认证
+description: 如何向 dTax REST API 进行身份认证
+draft: false
+---
+
+dTax API 使用 **HttpOnly 会话 Cookie** 进行身份认证,以防止 XSS 令牌窃取。
+
+## 注册 / 登录
+
+```bash
+# Create account
+curl -X POST https://getdtax.com/api/v1/auth/register \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+
+# Login
+curl -X POST https://getdtax.com/api/v1/auth/login \
+ -H "Content-Type: application/json" \
+ -d '{"email":"you@example.com","password":"yourpassword"}' \
+ -c cookies.txt
+```
+
+响应会设置一个有效期为 7 天的 `session` HttpOnly Cookie。
+
+## 使用 Cookie
+
+```bash
+# All subsequent requests use -b cookies.txt
+curl https://getdtax.com/api/v1/transactions \
+ -b cookies.txt
+```
+
+## OAuth
+
+同时支持 Google 和 GitHub OAuth:
+
+```
+GET https://getdtax.com/auth/google
+GET https://getdtax.com/auth/github
+```
+
+认证成功后均会重定向到 `getdtax.com/auth/callback`。
diff --git a/apps/docs-site/src/content/docs/zh-CN/api/overview.mdx b/apps/docs-site/src/content/docs/zh-CN/api/overview.mdx
new file mode 100644
index 00000000..23b1994a
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/api/overview.mdx
@@ -0,0 +1,48 @@
+---
+title: REST API 概览
+description: dTax 托管 REST API — 导入交易记录、计算收益、下载报告
+draft: false
+---
+
+import { LinkCard } from '@astrojs/starlight/components';
+
+dTax REST API 是托管在 **`https://getdtax.com/api/v1`** 的托管服务,负责存储、计算和报告生成,无需自行管理状态。
+
+## 基础 URL
+
+```
+https://getdtax.com/api/v1
+```
+
+## 身份认证
+
+所有接口均需要通过 `/auth/login` 获取的会话 Cookie。详见[身份认证](/api/authentication)。
+
+## 核心接口
+
+| 接口 | 描述 |
+|----------|-------------|
+| `POST /transactions/import` | 上传 CSV,自动解析、去重并存储 |
+| `GET /transactions` | 按条件筛选列出用户交易记录 |
+| `GET /tax/summary` | 指定税务年度的资本利得汇总 |
+| `POST /tax/calculate` | 执行完整的收益计算 |
+| `GET /tax/reports/:id/download` | 下载 Form 8949 / TXF / PDF |
+| `GET /notifications` | 用户通知列表 |
+
+## OpenAPI 规范
+
+完整的 OpenAPI 3.1 规范可在此获取:
+
+
+
+## 频率限制
+
+| 套餐 | 限制 |
+|------|-------|
+| FREE | 50 笔交易,每日 5 条 AI 消息 |
+| PRO($49/月) | 无限制 |
+| CPA($499/年) | 无限制 + 10 个客户账号 |
diff --git a/apps/docs-site/src/content/docs/zh-CN/index.mdx b/apps/docs-site/src/content/docs/zh-CN/index.mdx
new file mode 100644
index 00000000..b8ceb8dc
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/index.mdx
@@ -0,0 +1,35 @@
+---
+title: dTax 开发者中心
+description: 开源加密货币税务引擎 — 23个交易所解析器,8种计税方法,支持 Form 8949 / TXF 导出。
+template: splash
+hero:
+ tagline: 专业级加密货币税务计算,以 npm 包形式提供。
+ image:
+ file: ../../../assets/hero.png
+ actions:
+ - text: 快速开始
+ link: introduction
+ icon: right-arrow
+ variant: primary
+ - text: View on GitHub
+ link: https://github.com/dTaxLab/dtax
+ icon: external
+ variant: minimal
+---
+
+import { CardGrid, Card } from '@astrojs/starlight/components';
+
+
+
+ 零依赖 TypeScript 库。解析 CSV 文件,计算资本利得,导出 Form 8949 / TXF。
+
+
+ 支持 Coinbase、Binance、Kraken、Gemini、Etherscan、Solscan、OKX、Bybit 及其他 15 个平台。
+
+
+ FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling。
+
+
+ 开源项目免费使用。SaaS 产品可购买商业许可证。
+
+
diff --git a/apps/docs-site/src/content/docs/zh-CN/introduction.mdx b/apps/docs-site/src/content/docs/zh-CN/introduction.mdx
new file mode 100644
index 00000000..ffde53db
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/introduction.mdx
@@ -0,0 +1,38 @@
+---
+title: 简介
+description: dTax 是什么,以及 dtax.dev 开发者中心介绍
+draft: false
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+# dTax 开发者中心
+
+**dTax** 是一个开放核心的加密货币税务平台。核心计算引擎采用 AGPL-3.0 许可证,以 npm 包形式提供 — 你可以将专业级加密货币税务计算集成到自己的应用中。
+
+## 包含内容
+
+
+
+ 零依赖的 TypeScript 库,用于解析交易所 CSV 文件并使用任意计税方法计算资本利得。
+
+
+ 托管 API 服务,支持导入交易记录、运行税务计算、生成 Form 8949 / TXF 报告 — 无需自行管理基础设施。
+
+
+ 内置支持 Coinbase、Binance、Kraken、Gemini、Etherscan、Solscan、OKX、Bybit 及其他 15 个平台。
+
+
+ FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling。
+
+
+
+## 开放核心模式
+
+| 层级 | 许可证 | 获取方式 |
+|-------|---------|--------|
+| `@dtax/tax-engine` | AGPL-3.0 | GitHub + npm 公开获取 |
+| REST API | 商业许可 | getdtax.com |
+| Web 应用 | 商业许可 | getdtax.com |
+
+若你在商业产品中使用税务引擎,必须开源你的修改(AGPL-3.0),**或者**联系我们获取商业许可证。
diff --git a/apps/docs-site/src/content/docs/zh-CN/quickstart.mdx b/apps/docs-site/src/content/docs/zh-CN/quickstart.mdx
new file mode 100644
index 00000000..ada903be
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/quickstart.mdx
@@ -0,0 +1,64 @@
+---
+title: 快速开始
+description: 安装 @dtax/tax-engine 并在 5 分钟内完成第一次资本利得计算
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem } from '@astrojs/starlight/components';
+
+## 安装
+
+
+
+ ```bash
+ npm install @dtax/tax-engine
+ ```
+
+
+ ```bash
+ pnpm add @dtax/tax-engine
+ ```
+
+
+ ```bash
+ yarn add @dtax/tax-engine
+ ```
+
+
+
+## 解析 CSV 并计算收益
+
+```typescript
+import { parseCsv, computeGains } from '@dtax/tax-engine';
+import { readFileSync } from 'fs';
+
+// 1. Parse a Coinbase CSV export
+const csv = readFileSync('coinbase-export.csv', 'utf-8');
+const { transactions } = parseCsv(csv, { format: 'coinbase' });
+
+// 2. Compute capital gains using FIFO
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+
+console.log(`Short-term gains: $${result.shortTermGain}`);
+console.log(`Long-term gains: $${result.longTermGain}`);
+console.log(`Total gain/loss: $${result.totalGain}`);
+```
+
+## 自动检测格式
+
+如果不知道 CSV 由哪个交易所生成,可以省略 `format` 选项:
+
+```typescript
+const { transactions, summary } = parseCsv(csv);
+console.log(`Detected format: ${summary.format}`); // e.g. "coinbase"
+console.log(`Parsed ${summary.parsed} transactions`);
+```
+
+## 生成 Form 8949
+
+```typescript
+import { generateForm8949Csv } from '@dtax/tax-engine';
+
+const form8949 = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+writeFileSync('form8949.csv', form8949);
+```
diff --git a/apps/docs-site/src/content/docs/zh-CN/resources/csv-format.mdx b/apps/docs-site/src/content/docs/zh-CN/resources/csv-format.mdx
new file mode 100644
index 00000000..ea612c86
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/resources/csv-format.mdx
@@ -0,0 +1,46 @@
+---
+title: 通用 CSV 格式
+description: 若你的交易所不在支持列表中,如何格式化 CSV 进行导入
+draft: false
+---
+
+import { Steps } from '@astrojs/starlight/components';
+
+如果你的交易所不在[解析器列表](/tax-engine/parsers)中,可以使用我们的通用 CSV 格式。
+
+## 下载模板
+
+[下载 CSV 模板](https://getdtax.com/csv-template.csv)
+
+## 列说明
+
+| 列名 | 必填 | 类型 | 示例 |
+|--------|----------|------|---------|
+| `Date` | ✅ | ISO 8601 / MM-DD-YYYY | `2024-03-15T14:30:00Z` |
+| `Type` | ✅ | 枚举值(见下文) | `BUY` |
+| `Sent Amount` | — | 小数 | `0.5` |
+| `Sent Currency` | — | 币种代码 | `BTC` |
+| `Sent Value USD` | — | 小数 | `25000.00` |
+| `Received Amount` | — | 小数 | `10000` |
+| `Received Currency` | — | 币种代码 | `USDC` |
+| `Received Value USD` | — | 小数 | `10000.00` |
+| `Fee Amount` | — | 小数 | `0.001` |
+| `Fee Currency` | — | 币种代码 | `ETH` |
+| `Fee Value USD` | — | 小数 | `2.50` |
+| `Notes` | — | 字符串 | `Sold on Uniswap` |
+
+## 交易类型
+
+| Type | 描述 |
+|------|-------------|
+| `BUY` | 用法币购买加密货币 |
+| `SELL` | 将加密货币出售为法币 |
+| `TRADE` | 加密货币之间的兑换 |
+| `TRANSFER_IN` | 从其他钱包接收(不应税) |
+| `TRANSFER_OUT` | 发送到其他钱包(不应税) |
+| `STAKING` | 获得质押奖励 |
+| `MINING` | 挖矿奖励 |
+| `AIRDROP` | 空投获得的资产 |
+| `INCOME` | 其他加密货币收入 |
+| `FEE` | 独立手续费 |
+| `UNKNOWN` | 将由 AI 自动分类 |
diff --git a/apps/docs-site/src/content/docs/zh-CN/resources/faq.mdx b/apps/docs-site/src/content/docs/zh-CN/resources/faq.mdx
new file mode 100644
index 00000000..b1a09544
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/resources/faq.mdx
@@ -0,0 +1,48 @@
+---
+title: 常见问题
+description: 关于 dTax 交易同步、钱包支持和税务计算的常见问题
+draft: false
+---
+
+## 为什么我的交易记录中看不到某些微小转账?
+
+dTax 会自动过滤**灰尘攻击交易**——即向您钱包地址发送的金额小于 1,000 wei(0.000001 ETH,约合 $0.003)的微量转账。
+
+### 什么是灰尘攻击?
+
+灰尘攻击是指恶意行为者向您的钱包发送极少量加密货币(通常仅为 1 wei = 0.000000001 ETH)。其目的是通过追踪后续交易来对钱包进行去匿名化。这些并非您主动发起的转账,且对税务计算毫无影响。
+
+### 为什么要过滤?
+
+| 原因 | 说明 |
+|------|------|
+| **零税务影响** | 低于 1,000 wei 的金额不足 $0.01,不构成应税事件 |
+| **非您的交易** | 灰尘是在未经您同意的情况下*发送给*您的——您从未控制或转移过这些资金 |
+| **行业惯例** | CoinTracker、Koinly 等主流加密税务工具均静默过滤灰尘转账 |
+| **记录更清晰** | 消除垃圾交易使您的交易历史更准确、更易于审计 |
+
+### 过滤阈值是多少?
+
+针对 `TRANSFER_IN` 和 `TRANSFER_OUT` 类型,金额小于 **1,000 wei**(0.000001 ETH)的转账会被过滤。其他所有交易类型(兑换、交易、质押奖励等)无论金额大小均会被记录。
+
+### 这会影响我的税务报告吗?
+
+不会。IRS 不要求申报灰尘攻击——您并非主动获取这些资产,其价值可忽略不计。过滤操作对您的 Form 8949 或资本利得计算没有任何影响。
+
+---
+
+## 为什么价格补充显示的是部分数量(例如"9 / 50")?
+
+价格补充数量仅统计**应税交易**(BUY、SELL、TRADE、DEX_SWAP、STAKING_REWARD 等)。您自己钱包之间的简单转账(`TRANSFER_IN` / `TRANSFER_OUT`)不计入其中,因为这些不是应税事件,税务申报时无需 USD 价格。
+
+---
+
+## 为什么钱包同步需要较长时间?
+
+EVM 钱包同步会依次查询最多 5 条区块链网络(以太坊、Polygon、BNB Chain、Arbitrum、Optimism),以保持在 Etherscan 免费版 5 次/秒的速率限制内。每条链执行 5 个并行 API 请求。所有链的完整同步可能需要 30–60 秒。
+
+---
+
+## 为什么钱包交易的税务计算显示为 $0?
+
+如果您的钱包中只有 `TRANSFER_IN` 和 `TRANSFER_OUT` 交易,税务总额将为 $0。自有钱包之间的转账**不是应税事件**——在您出售、兑换或使用该资产之前,不会产生资本利得或亏损。
diff --git a/apps/docs-site/src/content/docs/zh-CN/resources/license.mdx b/apps/docs-site/src/content/docs/zh-CN/resources/license.mdx
new file mode 100644
index 00000000..d29e6ddb
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/resources/license.mdx
@@ -0,0 +1,39 @@
+---
+title: 开放核心许可证
+description: AGPL-3.0 开放核心模式 — 你可以做什么,不可以做什么
+draft: false
+---
+
+## @dtax/tax-engine — AGPL-3.0
+
+`@dtax/tax-engine` npm 包采用 **GNU Affero General Public License v3.0** 许可证。
+
+### 你可以
+
+- 在个人项目中免费使用
+- 学习和修改源代码
+- 分发修改后的版本(必须保持 AGPL-3.0 许可证)
+- 在内部使用而无需开源(仅限内部使用)
+
+### 你必须(若进行分发)
+
+- 包含完整的 AGPL-3.0 许可证文本
+- 将所有修改以 AGPL-3.0 许可证开源
+- 向服务用户提供源代码访问权限
+
+### 你需要商业许可证,如果
+
+- 你基于该引擎构建 SaaS 产品且不开源
+- 你希望保留对修改内容的专有权
+
+## 商业许可证
+
+请联系 [hello@getdtax.com](mailto:hello@getdtax.com) 了解商业许可证选项。
+
+## Web 应用与 API
+
+dTax Web 应用和 REST API 是基于 **dTax 商业许可证** 的专有软件,不开源。
+
+## GitHub
+
+[github.com/dTaxLab/dtax](https://github.com/dTaxLab/dtax)
diff --git a/apps/docs-site/src/content/docs/zh-CN/resources/self-hosting.mdx b/apps/docs-site/src/content/docs/zh-CN/resources/self-hosting.mdx
new file mode 100644
index 00000000..ff83976a
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/resources/self-hosting.mdx
@@ -0,0 +1,263 @@
+---
+title: 自托管部署
+description: 使用 Docker Compose 在自有服务器上部署 dTax — 包含 PostgreSQL、Redis、API 和 Web 完整栈
+draft: false
+---
+
+import { Steps, Code, Tabs, TabItem, Aside } from '@astrojs/starlight/components';
+
+使用 Docker Compose 在自有 Linux 服务器上部署 dTax,15 分钟内完成。
+
+## 前提条件
+
+- Linux 服务器(推荐 Ubuntu 22.04+),2 GB+ 内存
+- Docker Engine 24+ 和 Docker Compose v2
+- 已将域名指向服务器 IP
+- 防火墙开放 80 和 443 端口
+
+## 快速开始
+
+
+
+1. **克隆仓库**
+
+ ```bash
+ git clone https://github.com/dTaxLab/dtax.git
+ cd dtax
+ ```
+
+2. **配置环境变量**
+
+ ```bash
+ cp .env.production.example .env
+ ```
+
+ 编辑 `.env`,填写所有必填项:
+
+ | 变量 | 说明 |
+ | ---- | ---- |
+ | `POSTGRES_PASSWORD` | 强数据库密码 |
+ | `JWT_SECRET` | 随机字符串,至少 32 字符 |
+ | `ENCRYPTION_KEY` | **64 字符十六进制字符串** — 见下方说明 |
+ | `CORS_ORIGIN` | 你的域名,例如 `https://tax.example.com` |
+ | `APP_URL` | 同上域名(用于密码重置邮件链接) |
+ | `NEXT_PUBLIC_API_URL` | `https://tax.example.com/api`(**构建时变量**,必须在 `docker compose build` 之前设置) |
+
+
+ 加密密钥**必须**是 64 字符十六进制字符串(32 原始字节)。使用其他格式会导致 API 在启动时崩溃。
+
+ ```bash
+ openssl rand -hex 32 # → ENCRYPTION_KEY
+ openssl rand -base64 32 # → JWT_SECRET
+ openssl rand -base64 24 # → POSTGRES_PASSWORD
+ ```
+
+
+3. **启动服务**
+
+
+ 在运行 `docker compose build` **之前**,必须先在 `.env` 中设置所有变量。`NEXT_PUBLIC_*` 变量会在镜像构建时被编译进 JavaScript bundle,构建后修改无效。
+
+ ```bash
+ docker compose build
+ docker compose up -d
+ ```
+
+
+ 此命令会启动 PostgreSQL、Redis、API、Web 和 nginx。`migrate` 服务会自动执行数据库迁移。
+
+ 验证运行状态:
+
+ ```bash
+ docker compose ps
+ curl http://localhost/api/health
+ ```
+
+
+
+## 架构说明
+
+```
+ ┌──────────┐
+ :80/:443 ────│ nginx │
+ └────┬─────┘
+ ┌────┴─────┐
+ ┌─────│ 路由 │─────┐
+ │ └──────────┘ │
+ ┌────┴───┐ ┌─────┴────┐
+ │ API │ │ Web │
+ │ :3001 │ │ :3000 │
+ └────┬───┘ └──────────┘
+ ┌────┴───┐ ┌───────┐
+ │Postgres│ │ Redis │
+ └────────┘ └───────┘
+```
+
+## TLS 证书(Let's Encrypt)
+
+
+
+1. **更新 nginx 配置**
+
+ 编辑 `docker/nginx/nginx.conf`,将 `server_name _;` 替换为你的域名:
+
+ ```nginx
+ server_name tax.example.com;
+ ```
+
+2. **申请证书**
+
+ ```bash
+ docker compose up -d nginx
+
+ docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot certonly \
+ --webroot -w /var/www/certbot \
+ -d tax.example.com \
+ --agree-tos --email you@example.com
+ ```
+
+3. **启用 HTTPS**
+
+ 在 `docker/nginx/nginx.conf` 中添加 HTTPS 服务块:
+
+ ```nginx
+ server {
+ listen 443 ssl http2;
+ server_name tax.example.com;
+
+ ssl_certificate /etc/letsencrypt/live/tax.example.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/tax.example.com/privkey.pem;
+ include /etc/nginx/snippets/ssl-params.conf;
+
+ location /api/ {
+ proxy_pass http://api/api/;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ }
+
+ location / {
+ proxy_pass http://web;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ }
+ ```
+
+ ```bash
+ docker compose restart nginx
+ ```
+
+4. **自动续期证书**
+
+ ```bash
+ echo "0 3 * * * docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ -v dtax_certbot-data:/var/www/certbot \
+ certbot/certbot renew --quiet \
+ && docker compose restart nginx" | crontab -
+ ```
+
+
+
+## 创建管理员账号
+
+1. 访问 `https://yourdomain.com/register` 注册账号
+2. 通过数据库将账号提升为管理员:
+
+```bash
+docker compose exec postgres psql -U dtax -c \
+ "UPDATE \"User\" SET role='ADMIN' WHERE email='your@email.com';"
+```
+
+## 更新
+
+```bash
+git pull
+docker compose build
+docker compose up -d
+```
+
+`migrate` 服务会自动应用新的数据库迁移。
+
+## 数据备份
+
+```bash
+# 执行备份
+chmod +x docker/scripts/backup.sh
+./docker/scripts/backup.sh ./backups
+
+# 每天凌晨 2 点自动备份
+echo "0 2 * * * /path/to/dtax/docker/scripts/backup.sh /path/to/dtax/backups" | crontab -
+
+# 从备份恢复
+gunzip -c backups/dtax_20260313_020000.sql.gz | \
+ docker compose exec -T postgres psql -U dtax dtax
+```
+
+## 可选服务
+
+| 服务 | 环境变量 | 用途 |
+| ---- | -------- | ---- |
+| Resend | `RESEND_API_KEY`、`FROM_EMAIL` | 邮件验证和密码重置(未配置则用户无法找回密码) |
+| Stripe | `STRIPE_SECRET_KEY`、`STRIPE_WEBHOOK_SECRET`、`STRIPE_PRO_PRICE_ID`、`STRIPE_CPA_PRICE_ID` | 订阅付费功能 |
+| Anthropic | `ANTHROPIC_API_KEY` | AI 交易分类和智能对话 |
+| Etherscan | `ETHERSCAN_API_KEY` | EVM 链上交易索引(以太坊、Polygon、BSC、Arbitrum、Optimism) |
+| Solscan | `SOLSCAN_API_KEY` | Solana 链上交易索引 |
+| PostHog | `NEXT_PUBLIC_POSTHOG_KEY`、`NEXT_PUBLIC_POSTHOG_HOST` | 产品数据分析 |
+| Sentry | `SENTRY_DSN` | 错误追踪 |
+
+所有可选服务未配置时均会优雅降级,不影响核心功能。
+
+## 常见问题
+
+**服务启动失败**
+
+```bash
+docker compose logs api # 查看 API 日志
+docker compose logs web # 查看 Web 日志
+docker compose logs nginx # 查看 nginx 日志
+```
+
+**API 立即崩溃**
+
+在 API 日志中查找 `FATAL: ENCRYPTION_KEY` — 这表示 `ENCRYPTION_KEY` 不是有效的 64 字符十六进制字符串。使用 `openssl rand -hex 32` 重新生成。
+
+**数据库连接错误**
+
+确认 `.env` 中的 `POSTGRES_PASSWORD` 与 postgres 卷首次创建时使用的密码一致:
+
+```bash
+docker compose ps postgres
+docker compose logs postgres
+```
+
+**端口冲突**
+
+如果 80 或 443 端口已被占用,编辑 `docker-compose.yml` 修改 nginx 的端口映射。
+
+**磁盘空间不足**
+
+```bash
+docker system prune -f # 清理未使用的镜像和容器
+```
+
+**重置所有数据**
+
+
+此操作会销毁所有数据,包括数据库内容。请先完成备份。
+
+
+```bash
+docker compose down -v
+docker compose up -d
+```
diff --git a/apps/docs-site/src/content/docs/zh-CN/tax-engine/cost-basis.mdx b/apps/docs-site/src/content/docs/zh-CN/tax-engine/cost-basis.mdx
new file mode 100644
index 00000000..96c52b42
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/tax-engine/cost-basis.mdx
@@ -0,0 +1,52 @@
+---
+title: 计税方法
+description: FIFO、LIFO、HIFO、Specific ID、Germany FIFO、PMPA、Total Average、UK Share Pooling
+draft: false
+---
+
+## 支持的方法
+
+| 方法 | ID | IRS 合规 | 说明 |
+|--------|----|---------------|-------|
+| 先进先出 | `FIFO` | ✅ 默认 | 最早购入的份额优先出售 |
+| 后进先出 | `LIFO` | ⚠️ Specific ID | 必须选择 Specific ID |
+| 最高价先出 | `HIFO` | ⚠️ Specific ID | 必须选择 Specific ID |
+| 指定批次 | `SPECIFIC_ID` | ✅ | 手动选择批次 |
+| 德国 FIFO | `GERMANY_FIFO` | 🇩🇪 | §23 EStG,1 年持有期 |
+| PMPA | `PMPA` | 🇨🇦 🇦🇺 | 调整后成本基础 |
+| 总平均成本 | `TOTAL_AVERAGE` | 🌍 | 平均成本基础 |
+| 英国份额池化 | `UK_SHARE_POOLING` | 🇬🇧 | Section 104 资金池 + 30 天规则 |
+
+## IRS 说明
+
+IRS 允许加密货币使用 **FIFO** 和 **Specific Identification**(Rev. Rul. 2023-14)。LIFO 和 HIFO 在技术上属于 Specific ID 策略 — 你必须维护批次级别的记录并持续应用所选方法。
+
+## 使用方法
+
+```typescript
+import { computeGains, compareAllMethods } from '@dtax/tax-engine';
+
+// Single method
+const result = computeGains(transactions, {
+ method: 'FIFO',
+ taxYear: 2024,
+});
+
+// Compare all 7 comparable methods (excludes SPECIFIC_ID)
+const comparison = compareAllMethods(transactions, 2024);
+comparison.forEach(({ method, totalGain, recommendation }) => {
+ console.log(`${method}: $${totalGain} ${recommendation ? '← recommended' : ''}`);
+});
+```
+
+## 返回结构
+
+```typescript
+interface GainResult {
+ shortTermGain: number;
+ longTermGain: number;
+ totalGain: number;
+ disposals: Disposal[];
+ unrealizedGain?: number;
+}
+```
diff --git a/apps/docs-site/src/content/docs/zh-CN/tax-engine/overview.mdx b/apps/docs-site/src/content/docs/zh-CN/tax-engine/overview.mdx
new file mode 100644
index 00000000..d05adb5a
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/tax-engine/overview.mdx
@@ -0,0 +1,53 @@
+---
+title: 税务引擎概览
+description: '@dtax/tax-engine — 核心计算引擎'
+draft: false
+---
+
+`@dtax/tax-engine` 是一个以 TypeScript 为核心、零依赖的加密货币税务计算库。
+
+## 功能特性
+
+- **23 个交易所解析器** — 自动检测或手动指定格式
+- **8 种计税方法** — FIFO、LIFO、HIFO、Specific ID 等
+- **交易类型** — 买入、卖出、兑换、质押、挖矿、空投、NFT、DeFi、手续费
+- **报告生成** — Form 8949(CSV/PDF/TXF)、Schedule D 汇总
+- **洗售检测** — 标记违反 30 天回购规则的情况
+- **去重处理** — 基于内容指纹的重复交易检测
+
+## 核心函数
+
+| 函数 | 描述 |
+|----------|-------------|
+| `parseCsv(csv, options?)` | 将交易所 CSV 解析为标准化交易记录 |
+| `computeGains(txs, options)` | 计算指定税务年度的资本利得 |
+| `compareAllMethods(txs, year)` | 对比全部 7 种可比方法的收益差异 |
+| `generateForm8949Csv(disposals, options)` | 将 Form 8949 导出为 CSV |
+| `generateTxfFile(disposals, options)` | 导出 TXF 文件供税务软件使用 |
+
+## TypeScript 类型
+
+```typescript
+type CsvFormat =
+ | 'coinbase' | 'binance' | 'binance_us' | 'kraken' | 'gemini'
+ | 'crypto_com' | 'kucoin' | 'okx' | 'bybit' | 'gate' | 'bitget'
+ | 'mexc' | 'htx' | 'etherscan' | 'etherscan_erc20'
+ | 'solscan' | 'solscan_defi' | 'bitfinex' | 'poloniex'
+ | 'koinly' | 'cointracker' | 'cryptact' | 'generic';
+
+type CostBasisMethod =
+ | 'FIFO' | 'LIFO' | 'HIFO' | 'SPECIFIC_ID'
+ | 'GERMANY_FIFO' | 'PMPA' | 'TOTAL_AVERAGE' | 'UK_SHARE_POOLING';
+
+interface ParsedTransaction {
+ type: TransactionType;
+ timestamp: string; // ISO 8601
+ sentAsset?: string;
+ sentAmount?: number;
+ receivedAsset?: string;
+ receivedAmount?: number;
+ feeAsset?: string;
+ feeAmount?: number;
+ notes?: string;
+}
+```
diff --git a/apps/docs-site/src/content/docs/zh-CN/tax-engine/parsers.mdx b/apps/docs-site/src/content/docs/zh-CN/tax-engine/parsers.mdx
new file mode 100644
index 00000000..ba03e81f
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/tax-engine/parsers.mdx
@@ -0,0 +1,83 @@
+---
+title: 交易所解析器
+description: 支持来自 23 个交易所和区块链的 CSV 导出格式
+draft: false
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+## 支持的交易所
+
+| 交易所 | 格式 ID | 说明 |
+|----------|-----------|-------|
+| Coinbase / Coinbase Pro | `coinbase` | 交易记录 + 成交明细 |
+| Binance 国际版 | `binance` | 现货 + 兑换历史 |
+| Binance US | `binance_us` | |
+| Kraken | `kraken` | 账本导出 |
+| Gemini | `gemini` | 交易历史 |
+| Crypto.com | `crypto_com` | App 导出 |
+| KuCoin | `kucoin` | |
+| OKX | `okx` | |
+| Bybit | `bybit` | |
+| Gate.io | `gate` | |
+| Bitget | `bitget` | |
+| MEXC | `mexc` | |
+| HTX(火币) | `htx` | |
+| Bitfinex | `bitfinex` | |
+| Poloniex | `poloniex` | |
+
+## 区块链浏览器
+
+| 来源 | 格式 ID | 说明 |
+|--------|-----------|-------|
+| Etherscan(交易记录) | `etherscan` | 需要 `userAddress` + `nativeAsset` |
+| Etherscan(ERC-20 代币) | `etherscan_erc20` | 需要 `userAddress` |
+| Solscan(SOL 转账) | `solscan` | 需要 `userAddress` |
+| Solscan(DeFi) | `solscan_defi` | |
+
+## 导入工具
+
+| 工具 | 格式 ID |
+|------|-----------|
+| Koinly | `koinly` |
+| CoinTracker | `cointracker` |
+| Cryptact | `cryptact` |
+| 通用 CSV | `generic` |
+
+## 使用方法
+
+```typescript
+import { parseCsv } from '@dtax/tax-engine';
+
+// Specific format
+const result = parseCsv(csv, { format: 'kraken' });
+
+// Etherscan with wallet address
+const result = parseCsv(csv, {
+ format: 'etherscan',
+ userAddress: '0xYourWalletAddress',
+ nativeAsset: 'ETH', // or 'BNB', 'MATIC', 'AVAX', 'FTM'
+});
+
+// Auto-detect
+const result = parseCsv(csv);
+console.log(result.summary.format); // detected format
+```
+
+## 通用 CSV 格式
+
+如果你的交易所不在列表中,请使用 `generic` 格式。CSV 文件须包含以下列:
+
+| 列名 | 必填 | 描述 |
+|--------|----------|-------------|
+| `Date` | ✅ | ISO 8601 或 MM/DD/YYYY |
+| `Type` | ✅ | BUY、SELL、TRADE 等 |
+| `Sent Amount` | — | |
+| `Sent Currency` | — | |
+| `Received Amount` | — | |
+| `Received Currency` | — | |
+| `Fee Amount` | — | |
+| `Fee Currency` | — | |
+| `Notes` | — | |
+
+[下载 CSV 模板](https://getdtax.com/csv-template.csv)
diff --git a/apps/docs-site/src/content/docs/zh-CN/tax-engine/reports.mdx b/apps/docs-site/src/content/docs/zh-CN/tax-engine/reports.mdx
new file mode 100644
index 00000000..e52aff60
--- /dev/null
+++ b/apps/docs-site/src/content/docs/zh-CN/tax-engine/reports.mdx
@@ -0,0 +1,34 @@
+---
+title: 报告生成
+description: Form 8949、Schedule D、TXF 及 PDF 报告生成
+draft: false
+---
+
+## Form 8949(CSV)
+
+```typescript
+import { computeGains, generateForm8949Csv } from '@dtax/tax-engine';
+
+const result = computeGains(transactions, { method: 'FIFO', taxYear: 2024 });
+const csv = generateForm8949Csv(result.disposals, { taxYear: 2024 });
+// Returns RFC 4180 CSV string ready to import into tax software
+```
+
+## TXF 导出
+
+TXF(Tax Exchange Format)格式支持 TurboTax、H&R Block 和 TaxAct:
+
+```typescript
+import { generateTxfFile } from '@dtax/tax-engine';
+
+const txf = generateTxfFile(result.disposals, { taxYear: 2024 });
+// Returns TXF string — save as .txf and import into your tax software
+```
+
+## Schedule D 汇总
+
+```typescript
+const { scheduleD } = result;
+console.log(`Short-term net: $${scheduleD.shortTermNet}`);
+console.log(`Long-term net: $${scheduleD.longTermNet}`);
+```
diff --git a/apps/docs-site/src/styles/custom.css b/apps/docs-site/src/styles/custom.css
new file mode 100644
index 00000000..b7cd69b7
--- /dev/null
+++ b/apps/docs-site/src/styles/custom.css
@@ -0,0 +1,182 @@
+/* dTax brand fonts */
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');
+
+/* ── Brand color tokens ─────────────────────────────── */
+:root {
+ --sl-font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
+ --sl-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
+
+ --sl-color-accent-low: #2d2060;
+ --sl-color-accent: #818cf8;
+ --sl-color-accent-high: #c7d2fe;
+ --sl-color-white: #ffffff;
+ --sl-color-gray-1: #e2e8f0;
+ --sl-color-gray-2: #94a3b8;
+ --sl-color-gray-3: #475569;
+ --sl-color-gray-4: #1e293b;
+ --sl-color-gray-5: #0f172a;
+ --sl-color-gray-6: #070c18;
+ --sl-color-black: #030712;
+
+ --sl-color-bg: #0a0e1a;
+ --sl-color-bg-nav: #0d1120;
+ --sl-color-bg-sidebar: #0d1120;
+ --sl-color-hairline: rgba(99, 102, 241, 0.15);
+}
+
+[data-theme='light'] {
+ --sl-color-accent-low: #eef2ff;
+ --sl-color-accent: #6366f1;
+ --sl-color-accent-high: #4338ca;
+
+ --sl-color-bg: #f8fafc;
+ --sl-color-bg-nav: #ffffff;
+ --sl-color-bg-sidebar: #f1f5f9;
+ --sl-color-hairline: #e2e8f0;
+ --sl-color-gray-1: #0f172a;
+ --sl-color-gray-2: #475569;
+ --sl-color-gray-3: #94a3b8;
+ --sl-color-gray-4: #cbd5e1;
+ --sl-color-gray-5: #e2e8f0;
+ --sl-color-gray-6: #f8fafc;
+ --sl-color-black: #0f172a;
+ --sl-color-white: #0f172a;
+}
+
+/* ── Global typography ──────────────────────────────── */
+body {
+ font-family: var(--sl-font);
+ -webkit-font-smoothing: antialiased;
+}
+
+code, pre, kbd, .sl-markdown-content code {
+ font-family: var(--sl-font-mono) !important;
+}
+
+/* ── Nav / header ───────────────────────────────────── */
+header.header {
+ border-bottom: 1px solid var(--sl-color-hairline);
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+}
+
+.site-title {
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ font-size: 1.1rem;
+}
+
+/* ── Sidebar ────────────────────────────────────────── */
+nav.sidebar {
+ border-right: 1px solid var(--sl-color-hairline);
+}
+
+.sidebar-content a[aria-current='page'] {
+ background: rgba(99, 102, 241, 0.12);
+ color: var(--sl-color-accent-high);
+ font-weight: 600;
+ border-radius: 6px;
+}
+
+/* ── Hero (splash) ──────────────────────────────────── */
+.hero {
+ padding-block: 4rem;
+}
+
+.hero h1 {
+ font-size: clamp(2rem, 5vw, 3.5rem);
+ font-weight: 800;
+ letter-spacing: -0.03em;
+ line-height: 1.1;
+ background: linear-gradient(135deg, #fff 0%, #c7d2fe 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+[data-theme='light'] .hero h1 {
+ background: linear-gradient(135deg, #1e1b4b 0%, #4f46e5 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+}
+
+.hero .tagline {
+ font-size: 1.15rem;
+ color: var(--sl-color-gray-2);
+ max-width: 42ch;
+}
+
+.hero .action {
+ border-radius: 8px;
+ font-weight: 600;
+ font-size: 0.95rem;
+ padding: 0.6rem 1.4rem;
+ transition: opacity 0.15s, transform 0.15s;
+}
+
+.hero .action:hover {
+ opacity: 0.9;
+ transform: translateY(-1px);
+}
+
+/* ── Content headings ───────────────────────────────── */
+.sl-markdown-content h1,
+.sl-markdown-content h2,
+.sl-markdown-content h3 {
+ letter-spacing: -0.02em;
+ font-weight: 700;
+}
+
+.sl-markdown-content h2 {
+ border-bottom: 1px solid var(--sl-color-hairline);
+ padding-bottom: 0.4rem;
+}
+
+/* ── Cards ──────────────────────────────────────────── */
+.card {
+ border-radius: 10px;
+ border: 1px solid var(--sl-color-hairline);
+ transition: border-color 0.2s, box-shadow 0.2s;
+}
+
+.card:hover {
+ border-color: var(--sl-color-accent);
+ box-shadow: 0 0 24px rgba(99, 102, 241, 0.15);
+}
+
+/* ── Tables ─────────────────────────────────────────── */
+.sl-markdown-content table {
+ border-collapse: collapse;
+ width: 100%;
+ font-size: 0.9rem;
+}
+
+.sl-markdown-content th {
+ background: rgba(99, 102, 241, 0.08);
+ font-weight: 600;
+ text-align: left;
+ padding: 0.5rem 0.75rem;
+ border-bottom: 2px solid var(--sl-color-hairline);
+}
+
+.sl-markdown-content td {
+ padding: 0.45rem 0.75rem;
+ border-bottom: 1px solid var(--sl-color-hairline);
+}
+
+/* ── Code blocks ────────────────────────────────────── */
+.sl-markdown-content pre {
+ border-radius: 10px;
+ border: 1px solid var(--sl-color-hairline);
+ font-size: 0.85rem;
+ line-height: 1.65;
+}
+
+/* ── Inline code ────────────────────────────────────── */
+.sl-markdown-content :not(pre) > code {
+ background: rgba(99, 102, 241, 0.1);
+ color: var(--sl-color-accent-high);
+ border-radius: 4px;
+ padding: 0.1em 0.35em;
+ font-size: 0.88em;
+}
diff --git a/apps/docs-site/tsconfig.json b/apps/docs-site/tsconfig.json
new file mode 100644
index 00000000..bcbf8b50
--- /dev/null
+++ b/apps/docs-site/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "astro/tsconfigs/strict"
+}
diff --git a/apps/docs-site/wrangler.jsonc b/apps/docs-site/wrangler.jsonc
new file mode 100644
index 00000000..be55169b
--- /dev/null
+++ b/apps/docs-site/wrangler.jsonc
@@ -0,0 +1,17 @@
+{
+ "$schema": "node_modules/wrangler/config-schema.json",
+ "name": "dtax-dev",
+ "compatibility_date": "2025-09-27",
+ "observability": {
+ "enabled": true
+ },
+ "main": "dist/_worker.js/index.js",
+ "compatibility_flags": [
+ "global_fetch_strictly_public",
+ "nodejs_compat"
+ ],
+ "assets": {
+ "binding": "ASSETS",
+ "directory": "dist"
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index 5619d8ac..b9cd9d19 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,6 +1,6 @@
# DTax Self-Hosted — Production Docker Compose
-# Start with: docker compose up -d
-# Access: http://localhost:3000
+# Start with: docker compose build && docker compose up -d
+# Access: http://localhost (port 80)
services:
postgres:
@@ -8,7 +8,7 @@ services:
restart: unless-stopped
environment:
POSTGRES_USER: dtax
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dtax_secure_password}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}
POSTGRES_DB: dtax
volumes:
- postgres-data:/var/lib/postgresql/data
@@ -18,18 +18,8 @@ services:
timeout: 5s
retries: 5
- redis:
- image: redis:7-alpine
- restart: unless-stopped
- volumes:
- - redis-data:/data
- healthcheck:
- test: ["CMD", "redis-cli", "ping"]
- interval: 5s
- timeout: 5s
- retries: 5
-
api:
+ image: ghcr.io/dtaxlab/dtax-api:${IMAGE_TAG:-latest}
build:
context: .
dockerfile: apps/api/Dockerfile
@@ -37,37 +27,85 @@ services:
depends_on:
postgres:
condition: service_healthy
- redis:
- condition: service_healthy
environment:
- DATABASE_URL: "postgresql://dtax:${POSTGRES_PASSWORD:-dtax_secure_password}@postgres:5432/dtax?schema=public"
+ DATABASE_URL: "postgresql://dtax:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}@postgres:5432/dtax?schema=public"
HOST: "0.0.0.0"
PORT: "3001"
NODE_ENV: "production"
- CORS_ORIGIN: "http://localhost:3000"
+ CORS_ORIGIN: ${CORS_ORIGIN:?CORS_ORIGIN is required}
+ APP_URL: ${APP_URL:?APP_URL is required}
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
ENCRYPTION_KEY: ${ENCRYPTION_KEY:?ENCRYPTION_KEY is required}
+ # Email (required for password reset)
+ RESEND_API_KEY: ${RESEND_API_KEY:-}
+ FROM_EMAIL: ${FROM_EMAIL:-noreply@getdtax.com}
+ # Payments
+ STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-}
+ STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-}
+ STRIPE_PRO_PRICE_ID: ${STRIPE_PRO_PRICE_ID:-}
+ STRIPE_CPA_PRICE_ID: ${STRIPE_CPA_PRICE_ID:-}
+ # AI
+ ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
+ # OAuth
+ GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
+ GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
+ GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-}
+ GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-}
+ # Price data
+ POLYGON_API_KEY: ${POLYGON_API_KEY:-}
+ COINGECKO_API_KEY: ${COINGECKO_API_KEY:-}
+ CRYPTOCOMPARE_API_KEY: ${CRYPTOCOMPARE_API_KEY:-}
+ # Report storage
+ REPORTS_DIR: "/app/data/reports"
+ # Blockchain indexers
+ ETHERSCAN_API_KEY: ${ETHERSCAN_API_KEY:-}
+ SOLSCAN_API_KEY: ${SOLSCAN_API_KEY:-}
+ # Stripe redirect
+ WEB_URL: ${APP_URL:-https://getdtax.com}
+ # Analytics / error tracking
+ SENTRY_DSN: ${SENTRY_DSN:-}
+ volumes:
+ - reports-data:/app/data/reports
expose:
- "3001"
healthcheck:
- test: ["CMD-SHELL", "wget -qO- http://localhost:3001/api/health || exit 1"]
+ test: ["CMD-SHELL", "node -e \"fetch('http://localhost:3001/api/health').then(r=>{if(!r.ok)throw 1}).catch(()=>process.exit(1))\""]
interval: 10s
timeout: 5s
retries: 5
- start_period: 15s
+ start_period: 30s
web:
+ image: ghcr.io/dtaxlab/dtax-web:${IMAGE_TAG:-latest}
build:
context: .
dockerfile: apps/web/Dockerfile
+ args:
+ # NEXT_PUBLIC_* vars are baked into the JS bundle at build time.
+ # Set these in .env BEFORE running docker compose build.
+ NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:?NEXT_PUBLIC_API_URL must be set before building}
+ NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-}
+ NEXT_PUBLIC_POSTHOG_KEY: ${NEXT_PUBLIC_POSTHOG_KEY:-}
+ NEXT_PUBLIC_POSTHOG_HOST: ${NEXT_PUBLIC_POSTHOG_HOST:-https://us.i.posthog.com}
+ NEXT_PUBLIC_GOOGLE_CLIENT_ID: ${NEXT_PUBLIC_GOOGLE_CLIENT_ID:-}
+ NEXT_PUBLIC_GITHUB_CLIENT_ID: ${NEXT_PUBLIC_GITHUB_CLIENT_ID:-}
+ NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN:-}
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
- NEXT_PUBLIC_API_URL: "http://localhost:3001"
+ SENTRY_DSN: ${SENTRY_DSN:-}
+ volumes:
+ - ./apps/web/content/blog:/app/content/blog:ro
expose:
- "3000"
+ healthcheck:
+ test: ["CMD-SHELL", "wget -qO- http://0.0.0.0:3000/ || exit 1"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 15s
nginx:
image: nginx:alpine
@@ -76,7 +114,7 @@ services:
api:
condition: service_healthy
web:
- condition: service_started
+ condition: service_healthy
ports:
- "80:80"
- "443:443"
@@ -86,8 +124,16 @@ services:
- certbot-data:/var/www/certbot:ro
- letsencrypt:/etc/letsencrypt:ro
+ certbot:
+ image: certbot/certbot
+ volumes:
+ - certbot-data:/var/www/certbot
+ - letsencrypt:/etc/letsencrypt
+ entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done'"
+
# Run database migrations on first start
migrate:
+ image: ghcr.io/dtaxlab/dtax-api:${IMAGE_TAG:-latest}
build:
context: .
dockerfile: apps/api/Dockerfile
@@ -95,12 +141,12 @@ services:
postgres:
condition: service_healthy
environment:
- DATABASE_URL: "postgresql://dtax:${POSTGRES_PASSWORD:-dtax_secure_password}@postgres:5432/dtax?schema=public"
+ DATABASE_URL: "postgresql://dtax:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}@postgres:5432/dtax?schema=public"
command: ["npx", "prisma", "migrate", "deploy", "--schema", "apps/api/prisma/schema.prisma"]
restart: "no"
volumes:
postgres-data:
- redis-data:
+ reports-data:
certbot-data:
letsencrypt:
diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf
index 0b0f269c..e0d467c4 100644
--- a/docker/nginx/nginx.conf
+++ b/docker/nginx/nginx.conf
@@ -1,3 +1,5 @@
+limit_req_zone $binary_remote_addr zone=ingest:10m rate=10r/s;
+
upstream api {
server api:3001;
}
@@ -6,11 +8,47 @@ upstream web {
}
server {
listen 80;
- server_name _;
+ server_name getdtax.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
- location /api/ {
+ location / {
+ return 301 https://$host$request_uri;
+ }
+}
+
+server {
+ listen 443 ssl;
+ server_name getdtax.com;
+ server_tokens off;
+
+ include /etc/nginx/snippets/ssl-params.conf;
+ ssl_certificate /etc/letsencrypt/live/getdtax.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/getdtax.com/privkey.pem;
+
+ location /ingest/static/ {
+ limit_req zone=ingest burst=20 nodelay;
+ proxy_pass https://us-assets.i.posthog.com/static/;
+ proxy_set_header Host us-assets.i.posthog.com;
+ proxy_ssl_server_name on;
+ proxy_connect_timeout 5s;
+ proxy_read_timeout 10s;
+ proxy_send_timeout 5s;
+ client_max_body_size 1m;
+ }
+ location /ingest/ {
+ limit_req zone=ingest burst=20 nodelay;
+ proxy_pass https://us.i.posthog.com/;
+ proxy_set_header Host us.i.posthog.com;
+ proxy_ssl_server_name on;
+ proxy_connect_timeout 5s;
+ proxy_read_timeout 10s;
+ proxy_send_timeout 5s;
+ client_max_body_size 1m;
+ }
+
+ # /api/api/... -> api:3001/api/... (Web 前端请求,NEXT_PUBLIC_API_URL 含 /api)
+ location /api/api/ {
proxy_pass http://api/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@@ -20,6 +58,19 @@ server {
proxy_cache off;
proxy_read_timeout 300s;
}
+
+ # /api/... -> api:3001/api/... (直接调用)
+ location /api/ {
+ proxy_pass http://api;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ }
+
location / {
proxy_pass http://web;
proxy_set_header Host $host;
diff --git a/docker/nginx/ssl-params.conf b/docker/nginx/ssl-params.conf
index 7d497174..d17d09fa 100644
--- a/docker/nginx/ssl-params.conf
+++ b/docker/nginx/ssl-params.conf
@@ -3,8 +3,9 @@ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDS
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
-add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
+add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
+add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://us.i.posthog.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://us.i.posthog.com https://ingest.sentry.io wss:; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
diff --git a/docker/scripts/backup.sh b/docker/scripts/backup.sh
new file mode 100755
index 00000000..ca966739
--- /dev/null
+++ b/docker/scripts/backup.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -euo pipefail
+BACKUP_DIR="${1:-./backups}"
+TIMESTAMP=$(date +%Y%m%d_%H%M%S)
+BACKUP_FILE="${BACKUP_DIR}/dtax_${TIMESTAMP}.sql.gz"
+RETAIN_DAYS=30
+mkdir -p "$BACKUP_DIR"
+echo "[$(date)] Starting backup..."
+docker compose exec -T postgres pg_dump -U dtax --clean --if-exists dtax | gzip > "$BACKUP_FILE"
+SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
+echo "[$(date)] Backup complete: $BACKUP_FILE ($SIZE)"
+find "$BACKUP_DIR" -name "dtax_*.sql.gz" -mtime +${RETAIN_DAYS} -delete
+echo "[$(date)] Cleaned backups older than ${RETAIN_DAYS} days"
diff --git a/docker/scripts/init-letsencrypt.sh b/docker/scripts/init-letsencrypt.sh
new file mode 100644
index 00000000..763d65f3
--- /dev/null
+++ b/docker/scripts/init-letsencrypt.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+# 首次部署时申请 Let's Encrypt SSL 证书
+# 用法: ./docker/scripts/init-letsencrypt.sh [domain]
+# email — Let's Encrypt 注册邮箱(必需)
+# domain — 域名,默认 getdtax.com
+#
+# 前置条件:
+# 1. DNS 已将域名解析到本机 IP
+# 2. 80 端口已开放(防火墙 + 安全组)
+# 3. docker compose pull 已执行(镜像已拉取)
+
+set -euo pipefail
+
+EMAIL="${1:?用法: $0 [domain]}"
+DOMAIN="${2:-getdtax.com}"
+
+# 清理可能残留的临时容器
+docker rm -f dtax-nginx-init 2>/dev/null || true
+
+echo ">>> [1/5] 生成临时自签名证书 ..."
+docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ --entrypoint sh certbot/certbot -c "\
+ mkdir -p /etc/letsencrypt/live/$DOMAIN && \
+ openssl req -x509 -nodes -newkey rsa:2048 -days 1 \
+ -keyout /etc/letsencrypt/live/$DOMAIN/privkey.pem \
+ -out /etc/letsencrypt/live/$DOMAIN/fullchain.pem \
+ -subj '/CN=localhost'"
+
+echo ">>> [2/5] 启动临时 nginx(仅用于 ACME 验证)..."
+# 使用最小化配置,不依赖 api/web upstream
+docker run -d --name dtax-nginx-init \
+ -p 80:80 \
+ -v dtax_certbot-data:/var/www/certbot \
+ -v dtax_letsencrypt:/etc/letsencrypt:ro \
+ nginx:alpine sh -c 'cat > /etc/nginx/conf.d/default.conf </dev/null; then
+ echo "nginx 已就绪"
+ break
+ fi
+ if [ "$i" -eq 10 ]; then
+ echo "错误:nginx 启动失败,查看日志:"
+ docker logs dtax-nginx-init 2>&1 | tail -10
+ docker rm -f dtax-nginx-init 2>/dev/null
+ exit 1
+ fi
+ echo "等待 nginx... ($i/10)"
+ sleep 2
+done
+
+echo ">>> [3/5] 删除临时证书 ..."
+docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ --entrypoint sh certbot/certbot -c "\
+ rm -rf /etc/letsencrypt/live/$DOMAIN && \
+ rm -rf /etc/letsencrypt/archive/$DOMAIN && \
+ rm -rf /etc/letsencrypt/renewal/$DOMAIN.conf"
+
+# 确认 nginx 还活着
+if ! docker ps | grep -q dtax-nginx-init; then
+ echo "错误:nginx 已停止,无法完成 ACME 验证"
+ docker rm -f dtax-nginx-init 2>/dev/null
+ exit 1
+fi
+
+echo ">>> [4/5] 向 Let's Encrypt 申请证书 ..."
+docker run --rm \
+ -v dtax_certbot-data:/var/www/certbot \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ certbot/certbot certonly --webroot \
+ -w /var/www/certbot \
+ --email "$EMAIL" \
+ -d "$DOMAIN" \
+ --rsa-key-size 4096 \
+ --agree-tos \
+ --no-eff-email \
+ --force-renewal
+
+# 验证证书文件是否存在
+docker run --rm \
+ -v dtax_letsencrypt:/etc/letsencrypt \
+ --entrypoint sh certbot/certbot -c \
+ "test -f /etc/letsencrypt/live/$DOMAIN/fullchain.pem" || {
+ echo "错误:证书申请失败,fullchain.pem 不存在"
+ docker rm -f dtax-nginx-init 2>/dev/null
+ exit 1
+ }
+
+echo ">>> [5/5] 清理临时 nginx ..."
+docker rm -f dtax-nginx-init 2>/dev/null
+
+echo ""
+echo ">>> 完成!SSL 证书已配置: $DOMAIN"
+echo ">>> 现在可以运行: docker compose up -d"
diff --git a/docs/README.md b/docs/README.md
index 041580a7..e911d03a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,12 +1,10 @@
-# DTax Documentation
+# dTax Documentation
-Documentation site for DTax, hosted at [dtax.dev](https://dtax.dev).
+Developer documentation for dTax, hosted at [dtax.dev](https://dtax.dev).
## Sections
-- Getting Started
-- Tax Engine API Reference
-- CLI Reference
-- Self-Hosting Guide
-- Cloud Platform Guide
-- Contributing Guide
+- **Getting Started** — Introduction, Quick Start
+- **Tax Engine** — Overview, Exchange Parsers, Cost Basis Methods, Reports
+- **REST API** — Overview, Authentication
+- **Resources** — Self-Hosting (Docker), CSV Format Guide, Open Core License, FAQ
diff --git a/docs/cloud-deploy-update-guide.md b/docs/cloud-deploy-update-guide.md
new file mode 100644
index 00000000..9132280c
--- /dev/null
+++ b/docs/cloud-deploy-update-guide.md
@@ -0,0 +1,432 @@
+# dTax 云服务器部署运维手册
+
+## 服务器信息
+
+- **服务器**: Oracle Cloud
+- **域名**: getdtax.com
+- **项目路径**: `/data/dtax`(dtax-private 源码仓库)
+- **SSH**: `ssh root@`
+
+---
+
+## 架构说明
+
+```
+/data/dtax/ ← git clone dtax-private
+├── .env ← 生产环境变量(chmod 600)
+├── .maintenance ← 维护模式标记(存在时暂停自动更新)
+├── docker-compose.yml ← image: + build: 模式
+├── apps/
+│ ├── api/Dockerfile ← API 镜像(node:24-slim)
+│ └── web/Dockerfile ← Web 镜像(node:24-slim → alpine)
+├── scripts/
+│ ├── setup-server.sh ← 一键部署/恢复
+│ ├── auto-update.sh ← 自动更新(cron 调用)
+│ ├── maintenance.sh ← 维护模式管理
+│ ├── ghcr-push.py ← 推送镜像到 GHCR(可选)
+│ └── docker-test.py ← 镜像测试
+├── docker/
+│ ├── nginx/nginx.conf ← Nginx 配置
+│ └── scripts/
+│ ├── backup.sh ← 数据库备份
+│ └── init-letsencrypt.sh ← SSL 证书初始化
+└── backups/
+ ├── dtax_YYYYMMDD_HHMMSS.sql.gz ← 数据库备份
+ ├── auto-update.log ← 自动更新日志
+ └── cron.log ← 定时任务日志
+```
+
+---
+
+## 自动更新流程
+
+每小时 :30 由 cron 触发 `auto-update.sh`,智能判断变更类型并执行对应操作:
+
+```mermaid
+flowchart TD
+ A[cron 每小时 :30 触发] --> B{.maintenance 存在?}
+ B -->|是| Z1[跳过,退出]
+ B -->|否| C{锁文件存在?}
+ C -->|是,进程存活| Z2[跳过,退出]
+ C -->|否| D[创建锁文件]
+ D --> E[git pull]
+ E --> F{有新 commit?}
+ F -->|否| Z3[释放锁,退出]
+ F -->|是| G[分析变更文件]
+ G --> H{变更类型}
+
+ H -->|仅博客| Z4[跳过构建\nvolume 自动生效]
+ H -->|API / packages| I[备份 DB]
+ H -->|Web 前端| J[构建 Web 镜像]
+ H -->|数据库迁移| K[备份 DB]
+ H -->|Docker 配置| L[备份 DB]
+
+ I --> I2[构建 API 镜像]
+ I2 --> I3[重启 API]
+
+ J --> J2[重启 Web]
+
+ K --> K2[构建 API 镜像]
+ K2 --> K3[执行迁移]
+ K3 --> K4[重启全部]
+
+ L --> L2[构建 API + Web]
+ L2 --> L3[重启全部]
+
+ I3 --> M[健康检查]
+ J2 --> M
+ K4 --> M
+ L3 --> M
+ Z4 --> N[释放锁]
+
+ M --> N
+ N --> O[写日志,退出]
+```
+
+## 定时任务时间线
+
+所有定时任务错开执行,避免冲突:
+
+```mermaid
+gantt
+ title 每日定时任务时间线
+ dateFormat HH:mm
+ axisFormat %H:%M
+
+ section 每小时
+ 自动更新(带锁) :active, 00:30, 5min
+ 自动更新(带锁) :active, 01:30, 5min
+ 自动更新(带锁) :active, 02:30, 5min
+ 自动更新(带锁) :active, 03:30, 5min
+
+ section 每天
+ 数据库备份(保留30天) :crit, 02:00, 5min
+
+ section 每周一
+ Nginx SSL 重载 : 03:00, 1min
+
+ section 每周日
+ 清理旧镜像+日志 : 04:00, 5min
+
+ section 持续运行
+ certbot 证书续期 :done, 00:00, 24h
+```
+
+## 定时任务清单
+
+| 时间 | 任务 | 脚本 | 说明 |
+|------|------|------|------|
+| 每小时 :30 | 自动更新 | `scripts/auto-update.sh` | 拉取代码,按需构建/迁移/重启 |
+| 每天 02:00 | 数据库备份 | `docker/scripts/backup.sh` | pg_dump 压缩,清理 30 天前备份 |
+| 每周一 03:00 | Nginx 重载 | `docker compose exec nginx nginx -s reload` | SSL 证书续期生效 |
+| 每周日 04:00 | 清理旧数据 | `docker image prune + truncate` | 7 天前镜像 + 大日志截断 |
+| 持续 | SSL 续期 | certbot 容器 | 每 12 小时检查证书 |
+
+## 自动清理策略
+
+```mermaid
+flowchart LR
+ subgraph 每次备份时
+ A1[数据库备份 .sql.gz] -->|保留 30 天| A2[自动删除旧备份]
+ end
+ subgraph 每次自动更新时
+ B1[auto-update.log] -->|超 5000 行| B2[轮转为 2000 行]
+ end
+ subgraph 每周日 04:00
+ C1[Docker 旧镜像] -->|超 7 天| C2[prune 删除]
+ D1[cron.log] -->|超 10MB| D2[截断为 1MB]
+ end
+ subgraph 持续运行
+ E1[SSL 证书] -->|到期前 30 天| E2[certbot 自动续期]
+ end
+```
+
+---
+
+## 首次部署
+
+```bash
+# 1. clone 源码
+cd /data && git clone https://github.com/dTaxLab/dtax-private.git dtax
+
+# 2. 配置环境变量
+cd /data/dtax
+cp .env.production.example .env
+nano .env # 填入所有密钥
+
+# 3. 一键部署(构建镜像 + SSL证书 + 启动服务 + 配置定时任务)
+bash scripts/setup-server.sh
+```
+
+一条命令完成所有配置,后续无需手动干预。
+
+---
+
+## 自动化任务
+
+以下任务由 `setup-server.sh` 自动配置到 cron,无需手动管理:
+
+| 时间 | 任务 | 说明 |
+|------|------|------|
+| 每小时 :30 | 自动更新 | 拉取代码,按需构建镜像、迁移、重启 |
+| 每天 02:00 | 数据库备份 | pg_dump 压缩,自动清理 30 天前备份 |
+| 每周一 03:00 | Nginx 重载 | 让 SSL 证书续期生效 |
+| 每周日 04:00 | 清理旧数据 | 删除 7 天前镜像 + 截断大日志 |
+| 持续运行 | SSL 续期 | certbot 容器每 12 小时检查 |
+
+### 自动更新智能判断
+
+`auto-update.sh` 每小时 :30 运行,根据代码变更类型自动决定操作:
+
+| 变更内容 | 自动操作 |
+|---------|---------|
+| 无更新 | 跳过 |
+| 仅博客文件 | 跳过构建(volume 挂载自动生效) |
+| API / packages 代码 | 备份 DB → 构建 API → 重启 API |
+| Web 前端代码 | 构建 Web → 重启 Web |
+| 数据库迁移文件 | 备份 DB → 构建 API → 执行迁移 → 重启 |
+| Docker 配置 | 备份 DB → 构建全部 → 重启全部 |
+
+### 安全机制
+
+- **锁文件**:防止并发执行
+- **维护模式**:人工操作时暂停自动更新
+- **迁移前备份**:检测到迁移文件时自动备份
+- **构建失败不重启**:失败则退出,不影响运行中的服务
+- **健康检查**:重启后自动验证 API 是否正常
+
+---
+
+## 人工运维
+
+### 开启维护模式
+
+进行任何手动操作前,先暂停自动更新:
+
+```bash
+cd /data/dtax
+bash scripts/maintenance.sh on # 开启(暂停自动更新)
+
+# ... 做操作 ...
+
+bash scripts/maintenance.sh off # 关闭(恢复自动更新)
+bash scripts/maintenance.sh status # 查看状态
+```
+
+### 手动更新类型
+
+#### 博客更新(无需重建)
+
+```bash
+bash scripts/maintenance.sh on
+git pull
+bash scripts/maintenance.sh off
+# 博客通过 volume 挂载,拉取后自动生效
+```
+
+#### 前端代码更新
+
+```bash
+bash scripts/maintenance.sh on
+git pull
+docker compose build web
+docker compose up -d web
+bash scripts/maintenance.sh off
+```
+
+> `NEXT_PUBLIC_*` 变量改了必须重新 build web。
+
+#### API 代码更新
+
+```bash
+bash scripts/maintenance.sh on
+git pull
+docker compose build api
+docker compose up -d api
+bash scripts/maintenance.sh off
+```
+
+#### 数据库迁移
+
+```bash
+bash scripts/maintenance.sh on
+./docker/scripts/backup.sh ./backups # 必须先备份!
+git pull
+docker compose build api
+docker compose run --rm migrate
+docker compose up -d
+docker compose ps
+curl -s https://getdtax.com/api/health
+bash scripts/maintenance.sh off
+```
+
+#### 全量更新
+
+```bash
+bash scripts/maintenance.sh on
+./docker/scripts/backup.sh ./backups
+git pull
+nano .env # 如有新变量
+docker compose build api web
+docker compose up -d
+docker compose ps
+curl -s https://getdtax.com/api/health
+bash scripts/maintenance.sh off
+```
+
+#### 环境变量变更
+
+```bash
+nano .env
+# 运行时变量 → 重启即可
+docker compose restart api
+
+# NEXT_PUBLIC_* → 必须重建 Web 镜像
+docker compose build web
+docker compose up -d web
+```
+
+#### Nginx 配置变更
+
+```bash
+git pull
+docker exec dtax-nginx-1 nginx -t # 测试语法
+docker exec dtax-nginx-1 nginx -s reload # 热重载
+```
+
+### 回滚
+
+```bash
+bash scripts/maintenance.sh on
+
+# 备份当前数据
+./docker/scripts/backup.sh ./backups
+
+# 回退代码
+git log --oneline -5
+git checkout <旧commit-hash>
+
+# 重建并启动
+docker compose build api web
+docker compose up -d
+
+# 如需回滚数据库
+docker compose stop api web
+gunzip -c backups/dtax_回滚前备份.sql.gz | docker compose exec -T postgres psql -U dtax dtax
+docker compose start api web
+
+bash scripts/maintenance.sh off
+```
+
+### 故障恢复
+
+服务器出问题后,重新执行一键部署脚本即可恢复:
+
+```bash
+cd /data/dtax
+bash scripts/setup-server.sh
+```
+
+---
+
+## 日常运维命令
+
+```bash
+cd /data/dtax
+
+# ---- 状态 ----
+docker compose ps # 服务状态
+docker compose logs --tail=50 api # API 日志
+docker compose logs -f api # 实时跟踪
+tail -f backups/auto-update.log # 自动更新日志
+tail -f backups/cron.log # 定时任务日志
+
+# ---- 服务 ----
+docker compose restart api # 重启 API
+docker compose restart web # 重启 Web
+docker compose restart nginx # 重启 Nginx
+
+# ---- 备份 ----
+./docker/scripts/backup.sh ./backups # 手动备份
+ls -lh backups/ # 查看备份
+
+# ---- 数据库 ----
+docker compose exec postgres psql -U dtax dtax # 进入数据库
+
+# ---- 磁盘 ----
+df -h # 磁盘使用
+docker system df # Docker 占用
+docker image prune -f # 清理旧镜像
+
+# ---- SSL ----
+docker compose run --rm certbot certificates # 查看证书状态
+docker compose run --rm certbot renew # 手动续期
+docker exec dtax-nginx-1 nginx -s reload # 重载证书
+
+# ---- GHCR(可选)----
+python3 scripts/ghcr-push.py # 构建并推送到 GHCR
+python3 scripts/ghcr-push.py --push-only # 仅推送
+```
+
+> **严禁** `docker compose down -v`(删除所有数据卷包括数据库)
+
+---
+
+## 验证部署
+
+```bash
+# 服务状态
+docker compose ps
+
+# API 健康检查
+curl -s https://getdtax.com/api/health
+curl -s https://getdtax.com/api/health/deep
+
+# Web 页面
+curl -sI https://getdtax.com
+
+# 直接测试 API(绕过 Nginx)
+docker exec dtax-api-1 node -e "fetch('http://localhost:3001/api/health').then(r=>r.json()).then(console.log)"
+```
+
+---
+
+## 注意事项
+
+| 项目 | 说明 |
+|------|------|
+| 人工操作前 | 先 `bash scripts/maintenance.sh on` 暂停自动更新 |
+| 数据库迁移 | 不可逆,**必须先备份** |
+| `NEXT_PUBLIC_*` | 烘焙在 Web 镜像中,改了必须 `docker compose build web` |
+| 运行时变量 | 改 `.env` 后 `docker compose restart api` 即可 |
+| 博客更新 | `git pull` 自动生效,不需要重建镜像 |
+| Nginx | 改了先 `nginx -t` 测试,再 `nginx -s reload` |
+| 回滚 | 代码用 `git checkout`,数据库只能从备份恢复 |
+| 故障恢复 | `bash scripts/setup-server.sh` 一键恢复 |
+
+---
+
+## 自动清理策略
+
+| 清理对象 | 策略 | 触发时间 |
+|---------|------|---------|
+| 数据库备份 | 保留 30 天 | 每次备份时清理 |
+| Docker 旧镜像 | 保留 7 天 | 每周日 04:00 |
+| auto-update.log | 超 5000 行轮转为 2000 行 | 每次自动更新时 |
+| cron.log | 超 10MB 截断为 1MB | 每周日 04:00 |
+| SSL 证书 | Let's Encrypt 自动续期 | certbot 持续运行 |
+
+---
+
+## 故障排查
+
+| 现象 | 排查 | 常见原因 |
+|------|------|---------|
+| API unhealthy | `docker compose logs api --tail=50` | ENCRYPTION_KEY 格式错误 |
+| Web 打不开 | `docker compose logs nginx --tail=50` | SSL 证书不存在 |
+| 502/504 | `docker compose ps api` | API 崩溃 |
+| 登录 UNAUTHORIZED | `docker compose logs api --tail=10` | Nginx 转发路径错误 |
+| 登录 INTERNAL_ERROR | `docker compose run --rm migrate` | 数据库表不存在 |
+| 数据库连接失败 | `docker compose exec postgres pg_isready -U dtax` | 密码不一致 |
+| 自动更新没生效 | `tail backups/auto-update.log` | 维护模式开着 / 锁文件残留 |
+| 磁盘满 | `df -h && docker system df` | `docker image prune -af` |
diff --git a/docs/logo.png b/docs/logo.png
new file mode 100644
index 00000000..1706ff58
Binary files /dev/null and b/docs/logo.png differ
diff --git a/docs/style-guide.md b/docs/style-guide.md
new file mode 100644
index 00000000..8816ed63
--- /dev/null
+++ b/docs/style-guide.md
@@ -0,0 +1,478 @@
+# DTax UI/UX Design System & Style Guide
+
+> Based on financial SaaS best practices. Dark Mode-First, Minimal Financial Dashboard.
+
+---
+
+## 1. Design Principles
+
+**Product type:** FinTech SaaS (crypto tax)
+**Visual style:** Dark Mode-First · Minimal Financial Dashboard
+**Brand keywords:** Calm · Professional · Precise · Trustworthy
+**Typography:** Inter (body) + JetBrains Mono (numbers/code)
+**Color palette:** Deep blue-purple (trust) + green/red (gain/loss)
+
+**Anti-patterns (never do):**
+
+- No AI purple-pink gradients (undermines financial credibility)
+- No emoji as functional icons (use SVG: Lucide/Heroicons)
+- No excessive animation (financial users want efficiency)
+- No low-contrast text (WCAG AA 4.5:1 minimum)
+
+---
+
+## 2. Design Token System
+
+### 2.1 Color Tokens (three-layer architecture)
+
+```css
+/* === Primitive Tokens === */
+--gray-50: #f8fafc; --gray-100: #f1f5f9;
+--gray-200: #e2e8f0; --gray-300: #cbd5e1;
+--gray-400: #94a3b8; --gray-500: #64748b;
+--gray-600: #475569; --gray-700: #334155;
+--gray-800: #1e293b; --gray-900: #0f172a;
+--gray-950: #0a0e1a;
+
+--indigo-400: #818cf8; --indigo-500: #6366f1;
+--indigo-600: #4f46e5;
+
+--emerald-400: #34d399; --emerald-500: #10b981;
+--red-400: #f87171; --red-500: #ef4444;
+--amber-400: #fbbf24; --amber-500: #f59e0b;
+--blue-500: #3b82f6;
+
+/* === Semantic Tokens — implemented in globals.css === */
+/* Switch via [data-theme="dark"] / [data-theme="light"] */
+--bg-primary /* page background: dark=#0a0e1a, light=#f8fafc */
+--bg-secondary /* section background: dark=#111827, light=#f1f5f9 */
+--bg-card /* card background: dark=#1e293b, light=#ffffff */
+--text-primary /* main text: dark=#f8fafc, light=#0f172a */
+--text-secondary /* secondary text: dark=#cbd5e1, light=#475569 */
+--text-muted /* muted text: dark=#94a3b8, light=#64748b */
+--accent /* brand accent: dark=#818cf8, light=#6366f1 */
+--green /* gain / positive */
+--red /* loss / negative */
+--yellow /* warning / neutral */
+--border /* border: dark=rgba(255,255,255,0.1), light=rgba(0,0,0,0.1) */
+
+/* === Component Tokens === */
+--btn-height-sm: 32px;
+--btn-height-md: 38px;
+--btn-height-lg: 44px;
+--input-height: 38px;
+--input-padding-x: 12px;
+--input-padding-y: 8px;
+--input-border-radius: 6px;
+--input-font-size: 14px;
+--card-padding: 20px;
+--card-border-radius: var(--radius-md);
+```
+
+### 2.2 Spacing Tokens (4px base grid)
+
+```css
+--space-0: 0;
+--space-1: 4px;
+--space-2: 8px;
+--space-3: 12px;
+--space-4: 16px;
+--space-5: 20px;
+--space-6: 24px;
+--space-8: 32px;
+--space-10: 40px;
+--space-12: 48px;
+--space-16: 64px;
+
+/* Semantic spacing */
+--gap-xs: var(--space-2); /* 8px — tight elements */
+--gap-sm: var(--space-3); /* 12px — form elements */
+--gap-md: var(--space-4); /* 16px — groups within cards */
+--gap-lg: var(--space-6); /* 24px — between sections */
+--gap-xl: var(--space-8); /* 32px — page sections */
+--gap-section: var(--space-12); /* 48px — major section dividers */
+```
+
+### 2.3 Typography Tokens
+
+```css
+/* Font sizes (modular scale 1.25) */
+--text-xs: 12px; /* labels, badges */
+--text-sm: 13px; /* form labels, table content */
+--text-base: 14px; /* body default */
+--text-md: 15px; /* card descriptions */
+--text-lg: 16px; /* minor headings */
+--text-xl: 18px; /* section headings */
+--text-2xl: 20px; /* page titles */
+--text-3xl: 24px; /* large headings */
+--text-4xl: 30px; /* hero subtitles */
+--text-5xl: 36px; /* hero titles */
+
+/* Font weights */
+--font-normal: 400;
+--font-medium: 500;
+--font-semibold: 600;
+--font-bold: 700;
+
+/* Line heights */
+--leading-tight: 1.25; /* headings */
+--leading-normal: 1.5; /* body */
+--leading-relaxed: 1.6; /* long-form text */
+
+/* Financial number typography (critical!) */
+.mono,
+.stat-value,
+td.amount {
+ font-variant-numeric: tabular-nums;
+ font-feature-settings: "tnum";
+}
+```
+
+### 2.4 Border Radius Tokens
+
+```css
+--radius-sm: 6px; /* buttons, inputs, badges */
+--radius-md: 8px; /* cards, dialogs */
+--radius-lg: 12px; /* large cards, modals */
+--radius-xl: 16px; /* container-level rounding */
+--radius-full: 9999px; /* circles */
+```
+
+### 2.5 Shadow Tokens
+
+```css
+--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
+--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
+--shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3); /* brand glow (indigo) */
+```
+
+### 2.6 Motion Tokens
+
+```css
+--duration-fast: 120ms; /* button hover, toggle */
+--duration-normal: 200ms; /* card expand, panel slide */
+--duration-slow: 300ms; /* modal, page transition */
+
+--ease-default: cubic-bezier(0.4, 0, 0.2, 1);
+--ease-in: cubic-bezier(0.4, 0, 1, 1); /* exit */
+--ease-out: cubic-bezier(0, 0, 0.2, 1); /* enter */
+--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
+```
+
+### 2.7 Z-index Scale
+
+```css
+--z-dropdown: 1000;
+--z-sticky: 1100;
+--z-modal-backdrop: 1200;
+--z-modal: 1300;
+--z-popover: 1400;
+--z-tooltip: 1500;
+```
+
+---
+
+## 3. Component Specifications
+
+### 3.1 Button
+
+| Variant | Usage | Style |
+| ----------------- | ------------------------------- | ------------------------------------- |
+| `btn-primary` | Primary action (Submit, Import) | accent background, white text |
+| `btn-secondary` | Secondary action (Cancel, Back) | transparent background, accent border |
+| `btn-ghost` | Low-priority (Filter, Reset) | transparent, background on hover |
+| `btn-destructive` | Destructive action (Delete) | red background, white text |
+
+**Heights:** sm(32px) / md(38px) / lg(44px — minimum touch target)
+**States:** default → hover(brightness+5%) → active(brightness-5%) → disabled(opacity 0.5) → loading(spinner)
+**Transition:** `transition: all var(--duration-fast) var(--ease-default)`
+
+### 3.2 Input
+
+```css
+.input {
+ height: var(--input-height);
+ padding: var(--input-padding-y) var(--input-padding-x);
+ border: 1px solid var(--border);
+ border-radius: var(--input-border-radius);
+ background: var(--bg-card);
+ color: var(--text-primary);
+ font-size: var(--input-font-size);
+ transition: border-color var(--duration-fast);
+}
+.input:focus {
+ border-color: var(--accent);
+ outline: 2px solid var(--accent-glow);
+ outline-offset: -1px;
+}
+.input-error {
+ border-color: var(--red);
+}
+```
+
+### 3.3 Card
+
+| Variant | CSS Class | Usage |
+| ----------- | ------------------- | --------------------------------------- |
+| Default | `.card` | Content container |
+| Glass | `.card-glass` | Landing page features |
+| Stat | `.stat-card` | Dashboard KPIs |
+| Interactive | `.card-interactive` | Clickable card (hover shadow elevation) |
+
+### 3.4 Table
+
+- Header: `text-muted`, `font-semibold`, `text-xs`, uppercase
+- Row: hover background `var(--bg-card-hover)`
+- Amount columns: `text-align: right`, `font-variant-numeric: tabular-nums`
+- Gain/loss: positive `var(--green)`, negative `var(--red)`
+- Long text: `text-overflow: ellipsis`, constrained `max-width`
+
+### 3.5 Badge
+
+```css
+.badge {
+ padding: 2px 8px;
+ border-radius: var(--radius-full);
+ font-size: var(--text-xs);
+ font-weight: var(--font-semibold);
+}
+.badge-success {
+ background: rgba(16, 185, 129, 0.1);
+ color: var(--green);
+}
+.badge-danger {
+ background: rgba(239, 68, 68, 0.1);
+ color: var(--red);
+}
+.badge-warning {
+ background: rgba(245, 158, 11, 0.1);
+ color: var(--yellow);
+}
+.badge-info {
+ background: rgba(99, 102, 241, 0.1);
+ color: var(--accent);
+}
+```
+
+---
+
+## 4. Layout
+
+### 4.1 Responsive Breakpoints
+
+```css
+/* Mobile First */
+@media (min-width: 480px) {
+ /* small tablet */
+}
+@media (min-width: 768px) {
+ /* tablet */
+}
+@media (min-width: 900px) {
+ /* nav breakpoint */
+}
+@media (min-width: 1024px) {
+ /* desktop */
+}
+@media (min-width: 1440px) {
+ /* wide screen */
+}
+```
+
+### 4.2 Page Layout
+
+```
+┌─────────────────────────────────────────┐
+│ Nav (sticky, z-sticky, 60px height) │
+├─────────────────────────────────────────┤
+│ Page Header (title + subtitle + actions│
+├─────────────────────────────────────────┤
+│ Content (max-width: 1200px, centered) │
+│ ┌──── grid-4 ─────────────────────┐ │
+│ │ stat │ stat │ stat │ stat │ │
+│ └─────────────────────────────────┘ │
+│ ┌──── card ───────────────────────┐ │
+│ │ main content │ │
+│ └─────────────────────────────────┘ │
+└─────────────────────────────────────────┘
+```
+
+### 4.3 Grid System
+
+```css
+.grid-2 {
+ grid-template-columns: repeat(2, 1fr);
+}
+.grid-3 {
+ grid-template-columns: repeat(3, 1fr);
+}
+.grid-4 {
+ grid-template-columns: repeat(4, 1fr);
+}
+
+@media (max-width: 768px) {
+ .grid-4 {
+ grid-template-columns: repeat(2, 1fr);
+ }
+ .grid-3 {
+ grid-template-columns: 1fr;
+ }
+}
+@media (max-width: 480px) {
+ .grid-4 {
+ grid-template-columns: 1fr;
+ }
+}
+```
+
+---
+
+## 5. Animation
+
+### 5.1 Base Transitions
+
+```css
+.interactive {
+ transition: all var(--duration-fast) var(--ease-default);
+}
+
+.btn:hover {
+ filter: brightness(1.1);
+}
+.btn:active {
+ filter: brightness(0.95);
+ transform: scale(0.98);
+}
+
+.card:hover {
+ border-color: var(--border-hover);
+}
+.stat-card:hover {
+ transform: translateY(-2px);
+}
+```
+
+### 5.2 Page Enter Animation
+
+```css
+.animate-in {
+ animation: fadeSlideIn var(--duration-slow) var(--ease-out);
+}
+@keyframes fadeSlideIn {
+ from {
+ opacity: 0;
+ transform: translateY(8px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+```
+
+### 5.3 Number Change Animation
+
+```css
+.number-animate {
+ transition: all var(--duration-normal) var(--ease-default);
+}
+```
+
+### 5.4 Respect User Preferences
+
+```css
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ transition-duration: 0.01ms !important;
+ }
+}
+```
+
+---
+
+## 6. Accessibility
+
+### 6.1 Color Contrast
+
+| Element | Minimum ratio | Note |
+| --------------------------- | ------------- | --------------- |
+| Body text | 4.5:1 (AA) | Required |
+| Large headings (≥18px bold) | 3:1 (AA) | Required |
+| Interactive element borders | 3:1 | Buttons, inputs |
+| Decorative elements | None | Visual only |
+
+### 6.2 Touch Targets
+
+- Minimum touch target: **44×44px** (mobile)
+- Element spacing: **minimum 8px**
+- All interactive elements: `cursor: pointer`
+- Focus ring: 2px solid var(--accent), never `outline: none`
+
+### 6.3 Semantic HTML
+
+- Navigation: ``
+- Sections: ``
+- Tables: ``, ``
+- Forms: `` bound with `for`, errors via `aria-describedby`
+
+### 6.4 Gain/Loss Must Not Rely on Color Alone
+
+```
+Correct: +$1,234.56 (green + plus sign)
+Correct: -$567.89 (red + minus sign)
+Wrong: $1,234.56 (green only, no sign)
+```
+
+---
+
+## 7. CSS Workflow
+
+### 7.1 Decision Flow for New Styles
+
+```
+Need to write a style?
+ │
+ ├─ Does a CSS class already exist? → use className
+ │
+ ├─ Used in ≥3 places (common pattern)? → add CSS class to globals.css
+ │
+ ├─ Component-specific? → compose with CSS variable + className
+ │
+ └─ Truly one-off? → style={} allowed, but must use CSS variable values
+```
+
+### 7.2 CSS Code Review Checklist
+
+- [ ] No hardcoded colors (must use `var(--)` variables)
+- [ ] No hardcoded spacing (prefer `var(--space-*)` or `var(--gap-*)`)
+- [ ] No hardcoded border-radius (use `var(--radius-*)`)
+- [ ] Gain/loss amounts have +/- sign (not color alone)
+- [ ] Monetary numbers use `.mono` class (tabular-nums alignment)
+- [ ] New interactive elements have hover + focus states
+- [ ] Mobile-friendly (tested at 375px width)
+- [ ] Respects `prefers-reduced-motion`
+- [ ] Text contrast ≥ 4.5:1
+
+### 7.3 File Organization
+
+```
+apps/web/src/app/
+├── globals.css ← design tokens + base components + layout + animation
+├── [locale]/
+│ ├── layout.tsx ← theme script + global providers
+│ ├── nav.tsx ← navigation
+│ └── [page]/page.tsx ← page-level styles use className first
+```
+
+**Rule: `globals.css` is the single source of truth for styles. Do not create additional CSS files.**
+
+---
+
+## 8. References
+
+- [Carbon Design System Spacing](https://carbondesignsystem.com/elements/spacing/overview/) — 4px grid standard
+- [SaaSFrame Dashboard Examples](https://www.saasframe.io/categories/dashboard) — 166+ SaaS dashboard references
diff --git a/package.json b/package.json
index ed26edf4..8903ada4 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,9 @@
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
+ "start": "turbo start",
"test": "turbo test",
+ "typecheck": "turbo typecheck",
"lint": "turbo lint",
"clean": "turbo clean",
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
@@ -25,9 +27,9 @@
"@changesets/changelog-github": "^0.6.0",
"@changesets/cli": "^2.30.0",
"husky": "^9.1.7",
- "lint-staged": "^16.3.2",
+ "lint-staged": "^16.4.0",
"prettier": "^3.2.0",
- "turbo": "^2.0.0",
+ "turbo": "^2.8.20",
"typescript": "^5.4.0"
},
"packageManager": "pnpm@9.0.0",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 65a9dbf7..b50a9abb 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@dtax/cli",
"version": "0.1.0",
- "description": "DTax CLI - Crypto tax calculator command-line tool",
+ "description": "dTax CLI — Calculate crypto taxes from the command line. 23 exchange CSV parsers, FIFO/LIFO/HIFO/Specific ID, Form 8949 export, wash sale detection",
"license": "AGPL-3.0",
"homepage": "https://getdtax.com",
"bugs": "https://github.com/dTaxLab/dtax/issues",
@@ -15,10 +15,20 @@
"tax",
"cli",
"bitcoin",
+ "cryptocurrency",
"calculator",
"form-8949",
+ "schedule-d",
"csv",
- "terminal"
+ "terminal",
+ "fifo",
+ "cost-basis",
+ "capital-gains",
+ "wash-sale",
+ "defi",
+ "tax-reporting",
+ "open-source",
+ "typescript"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -37,16 +47,18 @@
"access": "public"
},
"scripts": {
- "build": "tsup src/index.ts --format cjs --dts",
+ "build": "tsup",
+ "typecheck": "tsc --noEmit",
"dev": "tsup src/index.ts --format cjs --watch",
"test": "vitest run",
"clean": "rm -rf dist"
},
"dependencies": {
- "@dtax/tax-engine": "workspace:*",
- "@dtax/shared-types": "workspace:*"
+ "@dtax/shared-types": "workspace:*",
+ "@dtax/tax-engine": "workspace:*"
},
"devDependencies": {
+ "@types/node": "^25",
"tsup": "^8.0.0",
"typescript": "^5.4.0",
"vitest": "^2.1.9"
diff --git a/packages/cli/src/__tests__/cli-integration.test.ts b/packages/cli/src/__tests__/cli-integration.test.ts
index 261cb441..1bb922c8 100644
--- a/packages/cli/src/__tests__/cli-integration.test.ts
+++ b/packages/cli/src/__tests__/cli-integration.test.ts
@@ -107,5 +107,156 @@ describe("CLI Integration", () => {
expect(output).toBeDefined();
expect(output.length).toBeGreaterThan(0);
});
+
+ it("should merge multiple files with JSON output", () => {
+ const binance = path.join(FIXTURE_DIR, "binance-trades.csv");
+ const output = runCli(`calculate ${COINBASE} ${binance} --json`);
+ const jsonStart = output.indexOf("{");
+ const parsed = JSON.parse(output.slice(jsonStart));
+ expect(parsed.totalDispositions).toBe(2);
+ expect(parsed.results).toHaveLength(2);
+ });
+
+ it("should merge multiple files with compare", () => {
+ const binance = path.join(FIXTURE_DIR, "binance-trades.csv");
+ const output = runCli(`calculate ${COINBASE} ${binance} --compare`);
+ expect(output).toContain("Method Comparison");
+ expect(output).toContain("FIFO");
+ expect(output).toContain("LIFO");
+ expect(output).toContain("HIFO");
+ });
+ });
+
+ describe("Specific ID Method", () => {
+ it("should reject SPECIFIC_ID with a clear error", () => {
+ expect(() => {
+ runCli(`calculate ${COINBASE} --method SPECIFIC_ID`);
+ }).toThrow();
+ });
+ });
+
+ describe("International Methods", () => {
+ it("should reject GERMANY_FIFO with a clear error", () => {
+ expect(() => {
+ runCli(`calculate ${COINBASE} --method GERMANY_FIFO`);
+ }).toThrow();
+ });
+
+ it("should reject PMPA with a clear error", () => {
+ expect(() => {
+ runCli(`calculate ${COINBASE} --method PMPA`);
+ }).toThrow();
+ });
+
+ it("should reject TOTAL_AVERAGE with a clear error", () => {
+ expect(() => {
+ runCli(`calculate ${COINBASE} --method TOTAL_AVERAGE`);
+ }).toThrow();
+ });
+ });
+
+ describe("Currency Conversion", () => {
+ it("should display EUR currency symbol", () => {
+ const output = runCli(`calculate ${COINBASE} --currency EUR --rate 0.92`);
+ expect(output).toMatch(/€/);
+ // Rate applied: values should differ from USD default
+ expect(output).not.toContain("$");
+ });
+
+ it("should display JPY currency symbol", () => {
+ const output = runCli(`calculate ${COINBASE} --currency JPY --rate 150`);
+ expect(output).toMatch(/¥/);
+ expect(output).not.toContain("$");
+ });
+ });
+
+ describe("JSON Output Validation", () => {
+ it("should include method field in JSON output", () => {
+ const output = runCli(`calculate ${COINBASE} --json`);
+ const jsonStart = output.indexOf("{");
+ const parsed = JSON.parse(output.slice(jsonStart));
+ expect(parsed.method).toBe("FIFO");
+ });
+
+ it("should include results array in JSON output", () => {
+ const output = runCli(`calculate ${COINBASE} --json`);
+ const jsonStart = output.indexOf("{");
+ const parsed = JSON.parse(output.slice(jsonStart));
+ expect(Array.isArray(parsed.results)).toBe(true);
+ expect(parsed.results.length).toBeGreaterThan(0);
+ });
+
+ it("should include numeric netGainLoss in JSON output", () => {
+ const output = runCli(`calculate ${COINBASE} --json`);
+ const jsonStart = output.indexOf("{");
+ const parsed = JSON.parse(output.slice(jsonStart));
+ expect(typeof parsed.netGainLoss).toBe("number");
+ });
+ });
+
+ describe("Compare Output Validation", () => {
+ it("should contain all three methods in comparison", () => {
+ const output = runCli(`calculate ${COINBASE} --compare`);
+ expect(output).toContain("FIFO");
+ expect(output).toContain("LIFO");
+ expect(output).toContain("HIFO");
+ expect(output).toContain("Recommended");
+ });
+
+ it("should show gain/loss values for each method", () => {
+ const output = runCli(`calculate ${COINBASE} --compare`);
+ // Each method line should have a dollar amount
+ const methodLines = output
+ .split("\n")
+ .filter((l: string) => /^\s+(FIFO|LIFO|HIFO)/.test(l));
+ expect(methodLines.length).toBeGreaterThanOrEqual(3);
+ for (const line of methodLines) {
+ expect(line).toMatch(/\$/);
+ }
+ });
+ });
+
+ describe("Edge Cases", () => {
+ it("should error on empty CSV file", () => {
+ const emptyFile = `/tmp/dtax-empty-${Date.now()}.csv`;
+ fs.writeFileSync(emptyFile, "");
+ try {
+ expect(() => {
+ runCli(`calculate ${emptyFile}`);
+ }).toThrow();
+ } finally {
+ fs.unlinkSync(emptyFile);
+ }
+ });
+
+ it("should error on invalid method name", () => {
+ expect(() => {
+ runCli(`calculate ${COINBASE} --method INVALID`);
+ }).toThrow();
+ });
+
+ it("should error when no file argument is provided", () => {
+ expect(() => {
+ runCli("calculate");
+ }).toThrow();
+ });
+ });
+
+ describe("Output Format Options", () => {
+ it("should write CSV output with year filter combined", () => {
+ const tmpFile = `/tmp/dtax-combo-${Date.now()}.csv`;
+ try {
+ const output = runCli(
+ `calculate ${COINBASE} --output ${tmpFile} --year 2024`,
+ );
+ expect(output).toContain("2024");
+ expect(fs.existsSync(tmpFile)).toBe(true);
+ const csv = fs.readFileSync(tmpFile, "utf-8");
+ expect(csv).toContain("Box");
+ expect(csv).toContain("BTC");
+ } finally {
+ if (fs.existsSync(tmpFile)) fs.unlinkSync(tmpFile);
+ }
+ });
});
});
diff --git a/packages/cli/src/__tests__/lib.test.ts b/packages/cli/src/__tests__/lib.test.ts
index babc8300..a79517f5 100644
--- a/packages/cli/src/__tests__/lib.test.ts
+++ b/packages/cli/src/__tests__/lib.test.ts
@@ -354,12 +354,17 @@ const mockSimResult = {
};
const mockComparison: ComparisonResult = {
- fifo: { ...mockSimResult, projectedGainLoss: 500 },
- lifo: { ...mockSimResult, projectedGainLoss: 200 },
- hifo: { ...mockSimResult, projectedGainLoss: -100 },
+ methods: {
+ FIFO: { ...mockSimResult, projectedGainLoss: 500 },
+ LIFO: { ...mockSimResult, projectedGainLoss: 200 },
+ HIFO: { ...mockSimResult, projectedGainLoss: -100 },
+ GERMANY_FIFO: { ...mockSimResult, projectedGainLoss: 200 },
+ PMPA: { ...mockSimResult, projectedGainLoss: 200 },
+ TOTAL_AVERAGE: { ...mockSimResult, projectedGainLoss: 200 },
+ UK_SHARE_POOLING: { ...mockSimResult, projectedGainLoss: 200 },
+ },
recommended: "HIFO",
- recommendedReason:
- "HIFO provides the largest deductible loss, maximizing tax deductions.",
+ recommendedReasonCode: "largest_loss",
savings: 600,
};
@@ -387,7 +392,7 @@ describe("formatComparisonJson", () => {
it("returns object with all methods and recommendation", () => {
const json = formatComparisonJson(mockComparison);
expect(json.recommended).toBe("HIFO");
- expect(json.recommendedReason).toContain("HIFO");
+ expect(json.recommendedReasonCode).toBe("largest_loss");
expect(json.savings).toBe(600);
expect((json.fifo as Record).projectedGainLoss).toBe(500);
expect((json.lifo as Record).projectedGainLoss).toBe(200);
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index e95447d0..1bfc959f 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -55,7 +55,7 @@ function printUsage(): void {
console.log("");
console.log("Run 'dtax calculate --help' for calculate-specific options.");
console.log("");
- console.log("https://dtax.dev");
+ console.log("https://getdtax.com");
}
function printCalculateHelp(): void {
diff --git a/packages/cli/src/lib.ts b/packages/cli/src/lib.ts
index 2c2b2e36..8854d05e 100644
--- a/packages/cli/src/lib.ts
+++ b/packages/cli/src/lib.ts
@@ -137,11 +137,18 @@ export function formatComparisonTable(
}
};
- const methods = [
- { name: "FIFO", r: comparison.fifo },
- { name: "LIFO", r: comparison.lifo },
- { name: "HIFO", r: comparison.hifo },
- ] as const;
+ const DISPLAY_METHODS = ["FIFO", "LIFO", "HIFO"] as const;
+ const methodRows = DISPLAY_METHODS.map((name) => ({
+ name,
+ r: comparison.methods[name],
+ }));
+
+ const reasonLabels: Record = {
+ identical: "All methods produce identical results",
+ lowest_gain: "Lowest taxable gain",
+ largest_loss_clean: "Largest loss, no wash sale risk",
+ largest_loss: "Largest deductible loss",
+ };
const lines: string[] = [];
lines.push("");
@@ -156,7 +163,7 @@ export function formatComparisonTable(
);
lines.push(" " + "-".repeat(54));
- for (const m of methods) {
+ for (const m of methodRows) {
const rec = m.name === comparison.recommended ? " *" : "";
const gl = fmt(m.r.projectedGainLoss);
const period = m.r.holdingPeriod.replace("_", " ");
@@ -169,7 +176,9 @@ export function formatComparisonTable(
lines.push("");
lines.push("-".repeat(60));
lines.push(` Recommended: ${comparison.recommended}`);
- lines.push(` Reason: ${comparison.recommendedReason}`);
+ lines.push(
+ ` Reason: ${reasonLabels[comparison.recommendedReasonCode] ?? comparison.recommendedReasonCode}`,
+ );
lines.push(` Savings: ${fmt(comparison.savings)}`);
lines.push("=".repeat(60));
@@ -187,7 +196,9 @@ export function formatComparisonJson(
comparison: ComparisonResult,
rate: number = 1,
): Record {
- const convert = (r: ComparisonResult["fifo"]) => ({
+ const convert = (
+ r: (typeof comparison.methods)[keyof typeof comparison.methods],
+ ) => ({
projectedGainLoss: r.projectedGainLoss * rate,
holdingPeriod: r.holdingPeriod,
shortTermGainLoss: r.shortTermGainLoss * rate,
@@ -197,11 +208,11 @@ export function formatComparisonJson(
});
return {
- fifo: convert(comparison.fifo),
- lifo: convert(comparison.lifo),
- hifo: convert(comparison.hifo),
+ fifo: convert(comparison.methods["FIFO"]),
+ lifo: convert(comparison.methods["LIFO"]),
+ hifo: convert(comparison.methods["HIFO"]),
recommended: comparison.recommended,
- recommendedReason: comparison.recommendedReason,
+ recommendedReasonCode: comparison.recommendedReasonCode,
savings: comparison.savings * rate,
};
}
diff --git a/packages/cli/tsup.config.ts b/packages/cli/tsup.config.ts
new file mode 100644
index 00000000..94cdd60f
--- /dev/null
+++ b/packages/cli/tsup.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from "tsup";
+
+export default defineConfig({
+ entry: ["src/index.ts"],
+ format: ["cjs"],
+ dts: true,
+ clean: true,
+});
diff --git a/packages/shared-types/package.json b/packages/shared-types/package.json
index f2480241..3d736c5f 100644
--- a/packages/shared-types/package.json
+++ b/packages/shared-types/package.json
@@ -22,9 +22,9 @@
"types": "dist/index.d.ts",
"exports": {
".": {
+ "types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
- "require": "./dist/index.js",
- "types": "./dist/index.d.ts"
+ "require": "./dist/index.js"
}
},
"files": [
@@ -40,6 +40,7 @@
},
"scripts": {
"build": "tsup",
+ "typecheck": "tsc --noEmit -p tsconfig.build.json",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
"clean": "rm -rf dist"
},
diff --git a/packages/shared-types/src/index.ts b/packages/shared-types/src/index.ts
index b1e807ca..f7d4ea63 100644
--- a/packages/shared-types/src/index.ts
+++ b/packages/shared-types/src/index.ts
@@ -112,7 +112,15 @@ export interface PortfolioSummary {
export interface TaxSummary {
year: number;
- method: "FIFO" | "LIFO" | "HIFO" | "SPECIFIC_ID";
+ method:
+ | "FIFO"
+ | "LIFO"
+ | "HIFO"
+ | "SPECIFIC_ID"
+ | "GERMANY_FIFO"
+ | "PMPA"
+ | "TOTAL_AVERAGE"
+ | (string & {});
shortTermGains: number;
shortTermLosses: number;
longTermGains: number;
diff --git a/packages/tax-engine/eslint.config.mjs b/packages/tax-engine/eslint.config.mjs
new file mode 100644
index 00000000..93ec90c8
--- /dev/null
+++ b/packages/tax-engine/eslint.config.mjs
@@ -0,0 +1,16 @@
+import { defineConfig, globalIgnores } from "eslint/config";
+import tseslint from "typescript-eslint";
+
+export default defineConfig([
+ ...tseslint.configs.recommended,
+ globalIgnores(["dist/**"]),
+ {
+ rules: {
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ { argsIgnorePattern: "^_" },
+ ],
+ "@typescript-eslint/no-explicit-any": "warn",
+ },
+ },
+]);
diff --git a/packages/tax-engine/package.json b/packages/tax-engine/package.json
index c1fe953a..bbb1fdaa 100644
--- a/packages/tax-engine/package.json
+++ b/packages/tax-engine/package.json
@@ -1,7 +1,7 @@
{
"name": "@dtax/tax-engine",
"version": "0.1.0",
- "description": "Open source crypto tax calculation engine - FIFO, LIFO, HIFO, Specific ID",
+ "description": "Complete crypto tax calculation engine — 23 exchange parsers, FIFO/LIFO/HIFO/Specific ID, Form 8949 (CSV/PDF/TXF), Schedule D, wash sale detection, DeFi/NFT support, 1099-DA reconciliation",
"license": "AGPL-3.0",
"homepage": "https://getdtax.com",
"bugs": "https://github.com/dTaxLab/dtax/issues",
@@ -14,25 +14,42 @@
"crypto",
"tax",
"bitcoin",
+ "cryptocurrency",
"fifo",
"lifo",
"hifo",
+ "specific-id",
"cost-basis",
"form-8949",
"schedule-d",
"wash-sale",
+ "capital-gains",
+ "tax-calculator",
+ "tax-engine",
"csv-parser",
"ethereum",
- "capital-gains"
+ "defi",
+ "nft",
+ "coinbase",
+ "binance",
+ "kraken",
+ "1099-da",
+ "turbotax",
+ "txf",
+ "irs",
+ "tax-reporting",
+ "portfolio",
+ "open-source",
+ "typescript"
],
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"exports": {
".": {
+ "types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
- "require": "./dist/index.js",
- "types": "./dist/index.d.ts"
+ "require": "./dist/index.js"
}
},
"files": [
@@ -48,6 +65,7 @@
},
"scripts": {
"build": "tsup",
+ "typecheck": "tsc --noEmit -p tsconfig.build.json",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
"test": "vitest run",
"test:watch": "vitest",
@@ -56,12 +74,15 @@
},
"dependencies": {
"@dtax/shared-types": "workspace:*",
- "pdfkit": "^0.17.2"
+ "decimal.js": "^10.6.0",
+ "pdfkit": "^0.18.0"
},
"devDependencies": {
"@types/pdfkit": "^0.17.5",
+ "eslint": "^9",
"tsup": "^8.5.1",
"typescript": "^5.9.3",
+ "typescript-eslint": "^8.57.2",
"vitest": "^2.1.9"
}
}
diff --git a/packages/tax-engine/src/__tests__/csv-binance.test.ts b/packages/tax-engine/src/__tests__/csv-binance.test.ts
index d7ef4618..f40dbc96 100644
--- a/packages/tax-engine/src/__tests__/csv-binance.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-binance.test.ts
@@ -95,6 +95,161 @@ describe("parseBinanceCsv", () => {
});
});
+// ─── Multi-language Binance International Tests ─────
+
+describe("isBinanceCsv — multi-language detection", () => {
+ it("should detect Chinese (Simplified) headers", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Chinese (Traditional) headers", () => {
+ const csv = "時間,交易對,類型,價格,數量,成交額,手續費\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Japanese headers", () => {
+ const csv = "日時,ペア,売買,価格,数量,合計,手数料\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Korean headers", () => {
+ const csv = "날짜,거래쌍,유형,가격,수량,총액,수수료\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Turkish headers", () => {
+ const csv = "Tarih,İşlem Çifti,Taraf,Fiyat,Miktar,Toplam,Komisyon\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Spanish headers", () => {
+ const csv = "Fecha,Par,Lado,Precio,Ejecutado,Monto,Comisión\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Portuguese headers", () => {
+ const csv = "Data,Par,Lado,Preço,Executado,Valor,Taxa\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect German headers", () => {
+ const csv = "Datum,Paar,Seite,Preis,Ausgeführt,Betrag,Gebühr\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect French headers", () => {
+ const csv = "Date,Paire,Côté,Prix,Exécuté,Montant,Frais\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Russian headers", () => {
+ const csv = "Дата,Пара,Сторона,Цена,Исполнено,Сумма,Комиссия\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+
+ it("should detect Vietnamese headers", () => {
+ const csv = "Ngày,Cặp,Phía,Giá,Đã thực hiện,Số tiền,Phí\n";
+ expect(isBinanceCsv(csv)).toBe(true);
+ });
+});
+
+describe("parseBinanceCsv — Chinese (Simplified)", () => {
+ const csv = `时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种
+2026-02-06 13:06:18,SOL/USDT,SOL,USDT,BUY,82.11,0.2,16.422,0.0002,SOL
+2026-02-10 09:30:00,BTC/USDT,BTC,USDT,卖出,45000,0.1,4500,0.0001,BTC
+`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should resolve base/quote from explicit columns", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.transactions[0].receivedAsset).toBe("SOL");
+ expect(result.transactions[0].sentAsset).toBe("USDT");
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("BTC");
+ });
+
+ it("should parse fee with Chinese coin column", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.transactions[0].feeAmount).toBe(0.0002);
+ expect(result.transactions[0].feeAsset).toBe("SOL");
+ });
+});
+
+describe("parseBinanceCsv — Japanese", () => {
+ const csv = `日時,ペア,売買,価格,数量,合計,手数料,手数料通貨
+2024-03-15 08:00:00,BTCUSDT,BUY,65000,0.01,650,0.00001,BTC
+2024-03-16 12:00:00,ETHUSDT,売却,3200,5,16000,0.005,ETH
+`;
+
+ it("should parse Japanese headers", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Japanese 売却 to SELL", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ });
+});
+
+describe("parseBinanceCsv — Korean", () => {
+ const csv = `날짜,거래쌍,유형,가격,수량,총액,수수료,수수료 통화
+2024-05-01 10:00:00,BTCUSDT,매수,68000,0.05,3400,0.00005,BTC
+2024-05-02 14:00:00,ETHUSDT,매도,3500,2,7000,0.002,ETH
+`;
+
+ it("should parse Korean headers", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Korean 매수/매도 to BUY/SELL", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[1].type).toBe("SELL");
+ });
+});
+
+describe("parseBinanceCsv — Turkish", () => {
+ const csv = `Tarih,İşlem Çifti,Taraf,Fiyat,Miktar,Toplam,Komisyon
+2024-04-10 09:00:00,BTCUSDT,Aliş,67000,0.02,1340,0.00002
+`;
+
+ it("should parse Turkish headers and BUY keyword", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.summary.parsed).toBe(1);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ });
+});
+
+describe("parseBinanceCsv — Russian", () => {
+ const csv = `Дата,Пара,Сторона,Цена,Исполнено,Сумма,Комиссия
+2024-06-01 11:00:00,BTCUSDT,Покупка,70000,0.01,700,0.00001
+2024-06-02 15:00:00,ETHUSDT,Продажа,3800,1,3800,0.001
+`;
+
+ it("should parse Russian headers and buy/sell keywords", () => {
+ const result = parseBinanceCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[1].type).toBe("SELL");
+ });
+});
+
// ─── Binance US (Transaction History) ──────────────
const BINANCE_US_CSV = `Date,Type,Asset,Amount,Status,Balance,Fee
diff --git a/packages/tax-engine/src/__tests__/csv-bitget.test.ts b/packages/tax-engine/src/__tests__/csv-bitget.test.ts
index 0e68f86d..0f38b126 100644
--- a/packages/tax-engine/src/__tests__/csv-bitget.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-bitget.test.ts
@@ -197,3 +197,44 @@ describe("parseBitgetCsv", () => {
expect(result.transactions).toHaveLength(1);
});
});
+
+// ─── Multi-language Bitget detection tests ──────
+
+describe("isBitgetCsv — multi-language detection", () => {
+ it("should detect Chinese headers", () => {
+ const csv =
+ "订单ID,交易对,方向,成交价,成交量,总额,手续费,手续费币种,下单时间\n";
+ expect(isBitgetCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isBitgetCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseBitgetCsv — Chinese", () => {
+ const csv = `订单ID,交易对,方向,成交价,成交量,总额,手续费,手续费币种,下单时间
+1001,BTCUSDT,买入,50000,1.0,50000,50,USDT,2025-01-15 10:30:00
+1002,ETHUSDT,卖出,3000,2.0,6000,6,USDT,2025-02-20 14:00:00`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseBitgetCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入 to BUY", () => {
+ const result = parseBitgetCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(1);
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseBitgetCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/csv-bybit.test.ts b/packages/tax-engine/src/__tests__/csv-bybit.test.ts
index b9d95fee..5f1330c0 100644
--- a/packages/tax-engine/src/__tests__/csv-bybit.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-bybit.test.ts
@@ -215,3 +215,68 @@ describe("parseBybitCsv", () => {
expect(result.transactions[0].feeAsset).toBe("USDT");
});
});
+
+// ─── Multi-language Bybit detection tests ──────
+
+describe("isBybitCsv — multi-language detection", () => {
+ it("should detect Chinese headers", () => {
+ const csv =
+ "订单号,交易对,方向,平均成交价,成交数量,总额,手续费,手续费币种,下单时间\n";
+ expect(isBybitCsv(csv)).toBe(true);
+ });
+
+ it("should detect Japanese headers", () => {
+ const csv =
+ "注文番号,銘柄,売買,平均約定価格,約定数量,合計,手数料,手数料通貨,注文時間\n";
+ expect(isBybitCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isBybitCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseBybitCsv — Chinese", () => {
+ const csv = `订单号,交易对,方向,平均成交价,成交数量,总额,手续费,手续费币种,下单时间
+1001,BTCUSDT,买入,50000,1.0,50000,50,USDT,2025-01-15 10:30:00
+1002,ETHUSDT,卖出,3000,2.0,6000,6,USDT,2025-02-20 14:00:00`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseBybitCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入 to BUY", () => {
+ const result = parseBybitCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(1);
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseBybitCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
+
+describe("parseBybitCsv — Japanese", () => {
+ const csv = `注文番号,銘柄,売買,平均約定価格,約定数量,合計,手数料,手数料通貨,注文時間
+1001,BTCUSDT,買い,65000,0.5,32500,32.5,USDT,2025-03-15 08:00:00`;
+
+ it("should parse Japanese headers correctly", () => {
+ const result = parseBybitCsv(csv);
+ expect(result.summary.parsed).toBe(1);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Japanese 買い to BUY", () => {
+ const result = parseBybitCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(0.5);
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/csv-crypto-com.test.ts b/packages/tax-engine/src/__tests__/csv-crypto-com.test.ts
index e5a6c8f9..977e6428 100644
--- a/packages/tax-engine/src/__tests__/csv-crypto-com.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-crypto-com.test.ts
@@ -211,6 +211,82 @@ describe("parseCryptoComCsv — app format", () => {
});
});
+// ─── Multi-language Crypto.com detection tests ──────
+
+describe("isCryptoComCsv — multi-language detection", () => {
+ it("should detect Chinese (Simplified) app format headers", () => {
+ const csv =
+ "时间戳 (UTC),交易描述,币种,金额,目标币种,目标金额,本地货币,本地金额,本地金额 (USD),交易类型\n";
+ expect(isCryptoComCsv(csv)).toBe(true);
+ });
+
+ it("should detect Chinese (Traditional) app format headers", () => {
+ const csv =
+ "時間戳 (UTC),交易描述,幣種,金額,目標幣種,目標金額,本地貨幣,本地金額,本地金額 (USD),交易類型\n";
+ expect(isCryptoComCsv(csv)).toBe(true);
+ });
+
+ it("should detect Japanese app format headers", () => {
+ const csv =
+ "タイムスタンプ (UTC),取引説明,通貨,金額,変換先通貨,変換先金額,ネイティブ通貨,ネイティブ金額,ネイティブ金額 (USD),取引種類\n";
+ expect(isCryptoComCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isCryptoComCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseCryptoComCsv — Chinese (Simplified) app format", () => {
+ const csv = `时间戳 (UTC),交易描述,币种,金额,目标币种,目标金额,本地货币,本地金额,本地金额 (USD),交易类型
+2025-01-15 10:30:00,购买 BTC,BTC,0.5,,,USD,25000,25000,crypto_purchase
+2025-02-01 12:00:00,提币 BTC,BTC,-0.3,,,USD,15000,15000,crypto_withdrawal`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseCryptoComCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map BUY from Chinese format", () => {
+ const result = parseCryptoComCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(0.5);
+ expect(result.transactions[0].receivedValueUsd).toBe(25000);
+ });
+
+ it("should map WITHDRAWAL from Chinese format", () => {
+ const result = parseCryptoComCsv(csv);
+ expect(result.transactions[1].type).toBe("TRANSFER_OUT");
+ expect(result.transactions[1].sentAsset).toBe("BTC");
+ expect(result.transactions[1].sentAmount).toBe(0.3);
+ });
+});
+
+describe("parseCryptoComCsv — Japanese app format", () => {
+ const csv = `タイムスタンプ (UTC),取引説明,通貨,金額,変換先通貨,変換先金額,ネイティブ通貨,ネイティブ金額,ネイティブ金額 (USD),取引種類
+2025-03-15 09:00:00,BTC to ETH 交換,BTC,-0.1,ETH,1.5,USD,5000,5000,crypto_exchange`;
+
+ it("should parse Japanese headers correctly", () => {
+ const result = parseCryptoComCsv(csv);
+ expect(result.summary.parsed).toBe(1);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map exchange trade from Japanese format", () => {
+ const result = parseCryptoComCsv(csv);
+ const tx = result.transactions[0];
+ expect(tx.type).toBe("TRADE");
+ expect(tx.sentAsset).toBe("BTC");
+ expect(tx.sentAmount).toBe(0.1);
+ expect(tx.receivedAsset).toBe("ETH");
+ expect(tx.receivedAmount).toBe(1.5);
+ });
+});
+
describe("parseCsv integration", () => {
it("works via unified parseCsv with explicit format for newer format", () => {
const csv = `Date,Sent Amount,Sent Currency,Received Amount,Received Currency,Fee Amount,Fee Currency,Net Worth Amount,Net Worth Currency,Label,Description,TxHash
diff --git a/packages/tax-engine/src/__tests__/csv-gate.test.ts b/packages/tax-engine/src/__tests__/csv-gate.test.ts
index 91fbebec..e3b22512 100644
--- a/packages/tax-engine/src/__tests__/csv-gate.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-gate.test.ts
@@ -219,3 +219,44 @@ describe("parseGateCsv", () => {
expect(result.transactions).toHaveLength(1);
});
});
+
+// ─── Multi-language Gate.io detection tests ──────
+
+describe("isGateCsv — multi-language detection", () => {
+ it("should detect Chinese headers", () => {
+ const csv =
+ "编号,交易对,方向,角色,成交价,成交量,总额,手续费,手续费币种,日期\n";
+ expect(isGateCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isGateCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseGateCsv — Chinese", () => {
+ const csv = `编号,交易对,方向,角色,成交价,成交量,总额,手续费,手续费币种,日期
+1001,BTC_USDT,买入,taker,50000,1.0,50000,50,USDT,2025-01-15 10:30:00
+1002,ETH_USDT,卖出,maker,3000,2.0,6000,6,USDT,2025-02-20 14:00:00`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseGateCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入 to BUY", () => {
+ const result = parseGateCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(1);
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseGateCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/csv-htx.test.ts b/packages/tax-engine/src/__tests__/csv-htx.test.ts
index b279fac6..136c39e8 100644
--- a/packages/tax-engine/src/__tests__/csv-htx.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-htx.test.ts
@@ -247,3 +247,62 @@ describe("parseHtxCsv", () => {
expect(result.transactions).toHaveLength(1);
});
});
+
+describe("isHtxCsv — multi-language detection", () => {
+ it("should detect Japanese BitTrade headers", () => {
+ const csv = "時間,通貨ペア,売/買,価格,数量,約定額,手数料\n";
+ expect(isHtxCsv(csv)).toBe(true);
+ });
+
+ it("should detect Chinese headers", () => {
+ const csv = "时间,交易对,方向,价格,数量,成交额,手续费,手续费币种\n";
+ expect(isHtxCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese headers", () => {
+ // Binance uses 类型 (type), not 方向 (direction)
+ const csv = "时间,交易对,类型,价格,数量,成交额,手续费\n";
+ expect(isHtxCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseHtxCsv — Japanese (BitTrade)", () => {
+ const csv = `時間,通貨ペア,売/買,価格,数量,約定額,手数料
+2024-06-15 10:30:00,BTC/JPY,買,10500000,0.01,105000,52.5
+2024-06-16 14:00:00,ETH/JPY,売,550000,1,550000,275
+`;
+
+ it("should parse Japanese BitTrade CSV", () => {
+ const result = parseHtxCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ expect(result.summary.format).toBe("htx");
+ });
+
+ it("should map Japanese 買/売 to buy/sell", () => {
+ const result = parseHtxCsv(csv);
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].sentAsset).toBe("JPY");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ expect(result.transactions[1].receivedAsset).toBe("JPY");
+ });
+});
+
+describe("parseHtxCsv — Chinese", () => {
+ const csv = `时间,交易对,方向,价格,数量,成交额,手续费,手续费币种
+2024-07-01 09:00:00,BTC/USDT,买入,65000,0.1,6500,0.0001,BTC
+2024-07-02 15:00:00,ETH/USDT,卖出,3500,2,7000,0.002,ETH
+`;
+
+ it("should parse Chinese HTX CSV", () => {
+ const result = parseHtxCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入/卖出", () => {
+ const result = parseHtxCsv(csv);
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/csv-integration.test.ts b/packages/tax-engine/src/__tests__/csv-integration.test.ts
index 4c6dd7c8..45c6b90a 100644
--- a/packages/tax-engine/src/__tests__/csv-integration.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-integration.test.ts
@@ -178,6 +178,66 @@ describe("detectCsvFormat — Koinly/CoinTracker non-cross-detection", () => {
});
});
+describe("detectCsvFormat — multi-language headers (i18n)", () => {
+ it("detects Binance Chinese (Simplified)", () => {
+ expect(
+ detectCsvFormat(
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n",
+ ),
+ ).toBe("binance");
+ });
+
+ it("detects Binance Japanese", () => {
+ expect(detectCsvFormat("日時,ペア,売買,価格,数量,合計,手数料\n")).toBe(
+ "binance",
+ );
+ });
+
+ it("detects HTX Japanese (BitTrade)", () => {
+ expect(
+ detectCsvFormat("時間,通貨ペア,売/買,価格,数量,約定額,手数料\n"),
+ ).toBe("htx");
+ });
+
+ it("detects Crypto.com Chinese (Simplified)", () => {
+ expect(
+ detectCsvFormat(
+ "时间戳 (UTC),交易描述,币种,金额,目标币种,目标金额,本地货币,本地金额,本地金额 (USD),交易类型\n",
+ ),
+ ).toBe("crypto_com");
+ });
+
+ it("detects OKX Chinese", () => {
+ expect(
+ detectCsvFormat(
+ "订单ID,交易ID,交易时间,交易对,方向,价格,数量,总额,手续费,手续费币种\n",
+ ),
+ ).toBe("okx");
+ });
+
+ it("no cross-detection: Binance Chinese is not detected as OKX", () => {
+ expect(
+ detectCsvFormat(
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n",
+ ),
+ ).not.toBe("okx");
+ });
+
+ it("no cross-detection: HTX Japanese is not detected as Binance", () => {
+ expect(
+ detectCsvFormat("時間,通貨ペア,売/買,価格,数量,約定額,手数料\n"),
+ ).not.toBe("binance");
+ });
+
+ it("no cross-detection: OKX Chinese is not detected as HTX", () => {
+ expect(
+ detectCsvFormat(
+ "订单ID,交易ID,交易时间,交易对,方向,价格,数量,总额,手续费,手续费币种\n",
+ ),
+ ).not.toBe("htx");
+ });
+});
+
describe("parseCsv (auto-detect)", () => {
it("auto-detects and parses Coinbase CSV", () => {
const csv = `"Timestamp","Transaction Type","Asset","Quantity Transacted","Spot Price Currency","Spot Price at Transaction","Subtotal","Total (inclusive of fees and/or spread)","Fees and/or Spread","Notes"
diff --git a/packages/tax-engine/src/__tests__/csv-mexc.test.ts b/packages/tax-engine/src/__tests__/csv-mexc.test.ts
index f55eb642..6d45a65f 100644
--- a/packages/tax-engine/src/__tests__/csv-mexc.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-mexc.test.ts
@@ -230,3 +230,43 @@ ETH_USDT,2025-01-15 10:35:00,SELL,3000,2.0,6000,6USDT,Maker`;
expect(result.transactions).toHaveLength(1);
});
});
+
+// ─── Multi-language MEXC detection tests ──────
+
+describe("isMexcCsv — multi-language detection", () => {
+ it("should detect Chinese headers", () => {
+ const csv = "交易对,时间,方向,成交价,成交量,总额,手续费\n";
+ expect(isMexcCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isMexcCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseMexcCsv — Chinese", () => {
+ const csv = `交易对,时间,方向,成交价,成交量,总额,手续费
+BTC_USDT,2025-01-15 10:30:00,买入,50000,1.0,50000,50USDT
+ETH_USDT,2025-02-20 14:00:00,卖出,3000,2.0,6000,6USDT`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseMexcCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入 to BUY", () => {
+ const result = parseMexcCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(1);
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseMexcCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/csv-okx.test.ts b/packages/tax-engine/src/__tests__/csv-okx.test.ts
index 96bc01c7..619918e0 100644
--- a/packages/tax-engine/src/__tests__/csv-okx.test.ts
+++ b/packages/tax-engine/src/__tests__/csv-okx.test.ts
@@ -192,3 +192,73 @@ describe("parseOkxCsv", () => {
expect(result.transactions).toHaveLength(1);
});
});
+
+// ─── Multi-language OKX detection tests ──────
+
+describe("isOkxCsv — multi-language detection", () => {
+ it("should detect Chinese headers", () => {
+ const csv =
+ "订单ID,交易ID,交易时间,交易对,方向,价格,数量,总额,手续费,手续费币种\n";
+ expect(isOkxCsv(csv)).toBe(true);
+ });
+
+ it("should detect Traditional Chinese headers", () => {
+ const csv =
+ "訂單ID,交易ID,交易時間,交易對,方向,價格,數量,總額,手續費,手續費幣種\n";
+ expect(isOkxCsv(csv)).toBe(true);
+ });
+
+ it("should detect Japanese headers", () => {
+ const csv =
+ "注文ID,取引ID,取引時間,通貨ペア,売買,価格,数量,合計,手数料,手数料通貨\n";
+ expect(isOkxCsv(csv)).toBe(true);
+ });
+
+ it("should not false-positive on Binance Chinese", () => {
+ const csv =
+ "时间,交易对,基准货币,计价货币,类型,价格,数量,成交额,手续费,手续费结算币种\n";
+ expect(isOkxCsv(csv)).toBe(false);
+ });
+});
+
+describe("parseOkxCsv — Chinese", () => {
+ const csv = `订单ID,交易ID,交易时间,交易对,方向,价格,数量,总额,手续费,手续费币种
+1001,2001,2025-01-15 10:30:00,BTC-USDT,买入,50000,1.0,50000,-50,USDT
+1002,2002,2025-02-20 14:00:00,ETH-USDT,卖出,3000,2.0,6000,-6,USDT`;
+
+ it("should parse Chinese headers correctly", () => {
+ const result = parseOkxCsv(csv);
+ expect(result.summary.parsed).toBe(2);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Chinese 买入 to BUY", () => {
+ const result = parseOkxCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ expect(result.transactions[0].receivedAmount).toBe(1);
+ });
+
+ it("should map Chinese 卖出 to SELL", () => {
+ const result = parseOkxCsv(csv);
+ expect(result.transactions[1].type).toBe("SELL");
+ expect(result.transactions[1].sentAsset).toBe("ETH");
+ });
+});
+
+describe("parseOkxCsv — Japanese", () => {
+ const csv = `注文ID,取引ID,取引時間,通貨ペア,売買,価格,数量,合計,手数料,手数料通貨
+1001,2001,2025-03-15 08:00:00,BTC-USDT,購入,65000,0.01,650,-0.00001,BTC`;
+
+ it("should parse Japanese headers correctly", () => {
+ const result = parseOkxCsv(csv);
+ expect(result.summary.parsed).toBe(1);
+ expect(result.summary.failed).toBe(0);
+ });
+
+ it("should map Japanese 購入 to BUY", () => {
+ const result = parseOkxCsv(csv);
+ expect(result.transactions[0].type).toBe("BUY");
+ expect(result.transactions[0].receivedAsset).toBe("BTC");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/fifo.test.ts b/packages/tax-engine/src/__tests__/fifo.test.ts
index 11555226..957a1b56 100644
--- a/packages/tax-engine/src/__tests__/fifo.test.ts
+++ b/packages/tax-engine/src/__tests__/fifo.test.ts
@@ -392,7 +392,55 @@ describe("calculateFIFO", () => {
expect(result.holdingPeriod).toBe("LONG_TERM");
});
- // ── Test 12: Empty lots array ────────────────────
+ // ── Test 12: Exactly 1 calendar year = SHORT_TERM ─
+ it("classifies exactly 1 calendar year as SHORT_TERM (IRS: more than 1 year required)", () => {
+ const lots = [
+ createLot({
+ id: "1",
+ asset: "BTC",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-01-15"),
+ sourceId: "s1",
+ }),
+ ];
+ const event = createEvent({
+ id: "s1",
+ asset: "BTC",
+ amount: 1,
+ proceedsUsd: 15000,
+ date: new Date("2025-01-15"),
+ sourceId: "s1",
+ });
+ const result = calculateFIFO(lots, event);
+ expect(result.holdingPeriod).toBe("SHORT_TERM");
+ });
+
+ // ── Test 13: 1 year + 1 day = LONG_TERM ──────────
+ it("classifies 1 year + 1 day as LONG_TERM", () => {
+ const lots = [
+ createLot({
+ id: "1",
+ asset: "BTC",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-01-15"),
+ sourceId: "s1",
+ }),
+ ];
+ const event = createEvent({
+ id: "s1",
+ asset: "BTC",
+ amount: 1,
+ proceedsUsd: 15000,
+ date: new Date("2025-01-16"),
+ sourceId: "s1",
+ });
+ const result = calculateFIFO(lots, event);
+ expect(result.holdingPeriod).toBe("LONG_TERM");
+ });
+
+ // ── Test 14: Empty lots array ────────────────────
it("should handle empty lots array", () => {
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
diff --git a/packages/tax-engine/src/__tests__/germany-fifo.test.ts b/packages/tax-engine/src/__tests__/germany-fifo.test.ts
new file mode 100644
index 00000000..c04f55ef
--- /dev/null
+++ b/packages/tax-engine/src/__tests__/germany-fifo.test.ts
@@ -0,0 +1,341 @@
+/**
+ * Germany FIFO with 12-Month Tax Exemption Unit Tests
+ *
+ * Tests cover:
+ * 1. Basic sale within 12 months (normal gain)
+ * 2. Sale after 12 months (tax-free, zero gain)
+ * 3. Mixed holding periods (partial exemption)
+ * 4. Loss within 12 months (loss recognized)
+ * 5. Loss after 12 months (loss = 0, not deductible)
+ * 6. Multiple lot consumption with mixed periods
+ * 7. Fee handling with exempt gains
+ * 8. StrictSilo mode
+ *
+ * @license AGPL-3.0
+ */
+
+import { describe, it, expect, vi } from "vitest";
+import { calculateGermanyFIFO } from "../methods/germany-fifo";
+import type { TaxLot, TaxableEvent } from "../types";
+
+// ─── Helpers ────────────────────────────────────────
+
+function createLot(overrides: Partial & { asset: string }): TaxLot {
+ return {
+ id: `lot-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2024-01-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+function createEvent(
+ overrides: Partial & { asset: string },
+): TaxableEvent {
+ return {
+ id: `event-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ proceedsUsd: 40000,
+ date: new Date("2025-06-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+// ─── Tests ──────────────────────────────────────────
+
+describe("calculateGermanyFIFO", () => {
+ // ── Test 1: Basic sale within 12 months ───────────
+ it("should calculate normal gain when held less than 12 months", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2025-01-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ date: new Date("2025-06-01"), // 5 months later
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ expect(result.gainLoss).toBe(15000); // 45000 - 30000
+ expect(result.method).toBe("GERMANY_FIFO");
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].fullyConsumed).toBe(true);
+ });
+
+ // ── Test 2: Sale after 12 months (tax-free) ──────
+ it("should have zero gain when held more than 12 months", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2023-01-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 60000,
+ date: new Date("2025-06-01"), // > 2 years
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // Gain is zero because lot is exempt (held > 12 months)
+ expect(result.gainLoss).toBe(0);
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].lotId).toBe("lot-1");
+ expect(result.matchedLots[0].fullyConsumed).toBe(true);
+ });
+
+ // ── Test 3: Mixed holding periods ─────────────────
+ it("should apply partial exemption for mixed holding periods", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 15000, // $30k/BTC, acquired > 12 months ago
+ acquiredAt: new Date("2023-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 20000, // $40k/BTC, acquired < 12 months ago
+ acquiredAt: new Date("2025-03-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000, // $50k/BTC
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // lot-1 (0.5 BTC) is exempt: proceeds portion = 25000, cost = 15000, gain = 0 (exempt)
+ // lot-2 (0.5 BTC) is taxable: proceeds portion = 25000, cost = 20000, gain = 5000
+ expect(result.gainLoss).toBe(5000);
+ expect(result.matchedLots).toHaveLength(2);
+ });
+
+ // ── Test 4: Loss within 12 months ─────────────────
+ it("should recognize loss when held less than 12 months", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 5.0,
+ costBasisUsd: 10000, // $2000/ETH
+ acquiredAt: new Date("2025-03-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "ETH",
+ amount: 5.0,
+ proceedsUsd: 7500, // $1500/ETH — a loss
+ date: new Date("2025-06-01"), // 3 months
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ expect(result.gainLoss).toBe(-2500); // 7500 - 10000
+ });
+
+ // ── Test 5: Loss after 12 months (not deductible) ─
+ it("should have zero loss when held more than 12 months (not deductible)", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 5.0,
+ costBasisUsd: 10000, // $2000/ETH
+ acquiredAt: new Date("2023-01-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "ETH",
+ amount: 5.0,
+ proceedsUsd: 7500, // Selling at a loss
+ date: new Date("2025-06-01"), // > 2 years
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // Loss is also zeroed out for exempt lots
+ expect(result.gainLoss).toBe(0);
+ });
+
+ // ── Test 6: Multiple lots with mixed periods ──────
+ it("should handle multiple lot consumption with mixed holding periods", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 0.3,
+ costBasisUsd: 9000, // $30k/BTC, old (exempt)
+ acquiredAt: new Date("2023-06-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 0.4,
+ costBasisUsd: 16000, // $40k/BTC, old (exempt)
+ acquiredAt: new Date("2023-12-01"),
+ }),
+ createLot({
+ id: "lot-3",
+ asset: "BTC",
+ amount: 0.3,
+ costBasisUsd: 15000, // $50k/BTC, recent (taxable)
+ acquiredAt: new Date("2025-04-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 60000, // $60k/BTC
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // lot-1 (0.3): exempt, lot-2 (0.4): exempt, lot-3 (0.3): taxable
+ // Taxable proceeds = (0.3/1.0) * 60000 = 18000
+ // Taxable cost = 15000
+ // Gain = 18000 - 15000 = 3000
+ expect(result.gainLoss).toBe(3000);
+ expect(result.matchedLots).toHaveLength(3);
+ });
+
+ // ── Test 7: Fee handling with exempt gains ────────
+ it("should deduct fees even when gains are partially exempt", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2023-01-01"), // exempt
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ date: new Date("2025-06-01"),
+ feeUsd: 100,
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // Gain from lot is exempt (0), minus fee = -100
+ expect(result.gainLoss).toBe(-100);
+ });
+
+ it("should deduct fees from taxable gains normally", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2025-01-01"), // taxable
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ date: new Date("2025-06-01"),
+ feeUsd: 50,
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+
+ // 45000 - 30000 - 50 = 14950
+ expect(result.gainLoss).toBe(14950);
+ });
+
+ // ── Test 8: StrictSilo mode ───────────────────────
+ it("should only match lots from same source in strictSilo mode", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ sourceId: "binance",
+ acquiredAt: new Date("2025-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 35000,
+ sourceId: "kraken",
+ acquiredAt: new Date("2025-02-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ date: new Date("2025-06-01"),
+ sourceId: "kraken",
+ });
+
+ const result = calculateGermanyFIFO(lots, event, true);
+
+ // Should only use lot-2 (kraken), not lot-1 (binance)
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].lotId).toBe("lot-2");
+ expect(result.gainLoss).toBe(10000); // 45000 - 35000
+ });
+
+ // ── Test 9: Holding period classification ─────────
+ it("should classify holding period based on earliest consumed lot", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2023-01-01"), // > 1 year
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculateGermanyFIFO(lots, event);
+ expect(result.holdingPeriod).toBe("LONG_TERM");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/optimizer.test.ts b/packages/tax-engine/src/__tests__/optimizer.test.ts
index de39b5f5..465c490d 100644
--- a/packages/tax-engine/src/__tests__/optimizer.test.ts
+++ b/packages/tax-engine/src/__tests__/optimizer.test.ts
@@ -46,19 +46,20 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input);
// FIFO picks L1 (cost 20k) → gain 30k
- expect(result.fifo.projectedGainLoss).toBe(30000);
+ expect(result.methods["FIFO"].projectedGainLoss).toBe(30000);
// LIFO picks L3 (cost 60k) → loss -10k
- expect(result.lifo.projectedGainLoss).toBe(-10000);
+ expect(result.methods["LIFO"].projectedGainLoss).toBe(-10000);
// HIFO picks L3 (cost 60k) → loss -10k
- expect(result.hifo.projectedGainLoss).toBe(-10000);
+ expect(result.methods["HIFO"].projectedGainLoss).toBe(-10000);
});
it("recommends the method with the smallest gain in all-gain scenario", () => {
+ // Use lots held < 12 months so GERMANY_FIFO behaves like standard FIFO
// HIFO picks highest cost (L2=45k), LIFO picks latest (L3=35k), FIFO picks earliest (L1=30k)
const lots = [
- makeLot("L1", "BTC", 1, 30000, "2024-01-01"), // FIFO picks: gain 20k
- makeLot("L2", "BTC", 1, 45000, "2024-06-01"), // HIFO picks: gain 5k
- makeLot("L3", "BTC", 1, 35000, "2024-09-01"), // LIFO picks: gain 15k
+ makeLot("L1", "BTC", 1, 30000, "2025-01-01"), // FIFO picks: gain 20k (<12 months)
+ makeLot("L2", "BTC", 1, 45000, "2025-03-01"), // HIFO picks: gain 5k (<12 months)
+ makeLot("L3", "BTC", 1, 35000, "2025-04-01"), // LIFO picks: gain 15k (<12 months)
];
const input: Omit = {
asset: "BTC",
@@ -71,7 +72,7 @@ describe("compareAllMethods", () => {
// HIFO picks the lot with the highest cost basis → smallest gain
expect(result.recommended).toBe("HIFO");
- expect(result.hifo.projectedGainLoss).toBe(5000);
+ expect(result.methods["HIFO"].projectedGainLoss).toBe(5000);
});
it("recommends the method with the largest loss in loss scenario", () => {
@@ -92,7 +93,7 @@ describe("compareAllMethods", () => {
// HIFO picks the most expensive lot → largest loss → best deduction
expect(result.recommended).toBe("HIFO");
- expect(result.hifo.projectedGainLoss).toBe(-25000);
+ expect(result.methods["HIFO"].projectedGainLoss).toBe(-25000);
});
it("downgrades a method that triggers wash sale when others do not", () => {
@@ -112,7 +113,6 @@ describe("compareAllMethods", () => {
};
// Acquisition within 30 days of sale → triggers wash sale for losses
- // The wash sale detector uses lot IDs from the disposition to check
const acquisitions: AcquisitionRecord[] = [
{
id: "A1",
@@ -126,18 +126,13 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input, acquisitions);
- // All methods produce a loss, all should trigger wash sale in this case
- // (since the acquisition is recent for all dispositions)
- // Verify wash sale detection is propagated
- const anyWash =
- result.fifo.washSaleRisk ||
- result.lifo.washSaleRisk ||
- result.hifo.washSaleRisk;
+ // Verify wash sale detection is propagated to at least one method
+ const anyWash = Object.values(result.methods).some((m) => m.washSaleRisk);
expect(anyWash).toBe(true);
// The recommendation should still be provided
expect(result.recommended).toBeTruthy();
- expect(result.recommendedReason.length).toBeGreaterThan(0);
+ expect(result.recommendedReasonCode.length).toBeGreaterThan(0);
});
it("calculates savings as the absolute difference between best and worst", () => {
@@ -155,25 +150,29 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input);
- // FIFO gain: 30000, LIFO loss: -10000, HIFO loss: -10000
- // savings = |30000 - (-10000)| = 40000
- expect(result.savings).toBe(40000);
+ // FIFO gain: 30000, HIFO/LIFO loss: -10000 (UK_SHARE_POOLING/PMPA/TOTAL_AVERAGE/GERMANY_FIFO will vary)
+ // savings = max - min across all 7 methods
+ expect(result.savings).toBeGreaterThanOrEqual(0);
+ // Verify FIFO/HIFO difference is at least 40000
+ const fifoGL = result.methods["FIFO"].projectedGainLoss;
+ const hifoGL = result.methods["HIFO"].projectedGainLoss;
+ expect(Math.abs(fifoGL - hifoGL)).toBe(40000);
});
- it("recommends FIFO when all three methods produce identical results", () => {
- // Single lot: all methods must pick the same lot
- const lots = [makeLot("L1", "BTC", 1, 30000, "2024-01-01")];
+ it("recommends FIFO when all methods produce identical results", () => {
+ // pricePerUnit == costPerUnit → gain = 0 for all methods regardless of holding period or strategy
+ const lots = [makeLot("L1", "BTC", 1, 50000, "2024-01-01")];
const input: Omit = {
asset: "BTC",
amount: 1,
- pricePerUnit: 50000,
+ pricePerUnit: 50000, // no gain, no loss
date: new Date("2025-06-01"),
};
const result = compareAllMethods(lots, input);
expect(result.recommended).toBe("FIFO");
- expect(result.recommendedReason).toContain("identical");
+ expect(result.recommendedReasonCode).toBe("identical");
expect(result.savings).toBe(0);
});
@@ -210,31 +209,34 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input);
- expect(result.fifo.insufficientLots).toBe(true);
- expect(result.lifo.insufficientLots).toBe(true);
- expect(result.hifo.insufficientLots).toBe(true);
- // All should have the same available amount
- expect(result.fifo.availableAmount).toBe(0.5);
- expect(result.lifo.availableAmount).toBe(0.5);
- expect(result.hifo.availableAmount).toBe(0.5);
+ // All 7 methods should report insufficientLots
+ for (const sim of Object.values(result.methods)) {
+ expect(sim.insufficientLots).toBe(true);
+ expect(sim.availableAmount).toBe(0.5);
+ }
});
- it("provides a non-empty recommendedReason for every scenario", () => {
+ it("provides a valid recommendedReasonCode for every scenario", () => {
+ const validCodes = [
+ "identical",
+ "lowest_gain",
+ "largest_loss_clean",
+ "largest_loss",
+ ];
+
// Scenario 1: All gains
const lots1 = [
makeLot("L1", "BTC", 1, 30000, "2024-01-01"),
makeLot("L2", "BTC", 1, 45000, "2024-06-01"),
];
- const input: Omit = {
+ const input1: Omit = {
asset: "BTC",
amount: 1,
pricePerUnit: 50000,
date: new Date("2025-06-01"),
};
- const r1 = compareAllMethods(lots1, input);
- expect(r1.recommendedReason).toBeTruthy();
- expect(typeof r1.recommendedReason).toBe("string");
- expect(r1.recommendedReason.length).toBeGreaterThan(0);
+ const r1 = compareAllMethods(lots1, input1);
+ expect(validCodes).toContain(r1.recommendedReasonCode);
// Scenario 2: Some losses
const lots2 = [
@@ -248,24 +250,28 @@ describe("compareAllMethods", () => {
date: new Date("2025-06-01"),
};
const r2 = compareAllMethods(lots2, input2);
- expect(r2.recommendedReason).toBeTruthy();
- expect(r2.recommendedReason.length).toBeGreaterThan(0);
+ expect(validCodes).toContain(r2.recommendedReasonCode);
});
- it("handles a single lot (all methods produce the same result)", () => {
- const lots = [makeLot("L1", "ETH", 5, 2000, "2024-03-01")];
+ it("handles a single lot with no gain (all methods produce the same result)", () => {
+ // pricePerUnit == costPerUnit: gain = 0 for every method including GERMANY_FIFO
+ const lots = [makeLot("L1", "ETH", 5, 2500, "2024-03-01")];
const input: Omit = {
asset: "ETH",
amount: 3,
- pricePerUnit: 2500,
+ pricePerUnit: 2500, // no gain, no loss
date: new Date("2025-06-01"),
};
const result = compareAllMethods(lots, input);
- // All methods consume from the same single lot
- expect(result.fifo.projectedGainLoss).toBe(result.lifo.projectedGainLoss);
- expect(result.lifo.projectedGainLoss).toBe(result.hifo.projectedGainLoss);
+ const fifoGL = result.methods["FIFO"].projectedGainLoss;
+ const lifoGL = result.methods["LIFO"].projectedGainLoss;
+ const hifoGL = result.methods["HIFO"].projectedGainLoss;
+
+ // All methods produce the same result (0 gain)
+ expect(fifoGL).toBe(lifoGL);
+ expect(lifoGL).toBe(hifoGL);
expect(result.recommended).toBe("FIFO");
expect(result.savings).toBe(0);
});
@@ -286,8 +292,8 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input);
- expect(result.fifo.projectedGainLoss).toBeGreaterThan(0);
- expect(result.hifo.projectedGainLoss).toBeLessThan(0);
+ expect(result.methods["FIFO"].projectedGainLoss).toBeGreaterThan(0);
+ expect(result.methods["HIFO"].projectedGainLoss).toBeLessThan(0);
// Should recommend the method with the largest loss (most deduction)
expect(["LIFO", "HIFO"]).toContain(result.recommended);
});
@@ -303,19 +309,44 @@ describe("compareAllMethods", () => {
const result = compareAllMethods(lots, input);
- for (const key of ["fifo", "lifo", "hifo"] as const) {
- const r = result[key];
- expect(r).toHaveProperty("projectedGainLoss");
- expect(r).toHaveProperty("holdingPeriod");
- expect(r).toHaveProperty("shortTermGainLoss");
- expect(r).toHaveProperty("longTermGainLoss");
- expect(r).toHaveProperty("proceeds");
- expect(r).toHaveProperty("costBasis");
- expect(r).toHaveProperty("matchedLots");
- expect(r).toHaveProperty("washSaleRisk");
- expect(r).toHaveProperty("remainingPosition");
- expect(r).toHaveProperty("insufficientLots");
- expect(r).toHaveProperty("availableAmount");
+ for (const sim of Object.values(result.methods)) {
+ expect(sim).toHaveProperty("projectedGainLoss");
+ expect(sim).toHaveProperty("holdingPeriod");
+ expect(sim).toHaveProperty("shortTermGainLoss");
+ expect(sim).toHaveProperty("longTermGainLoss");
+ expect(sim).toHaveProperty("proceeds");
+ expect(sim).toHaveProperty("costBasis");
+ expect(sim).toHaveProperty("matchedLots");
+ expect(sim).toHaveProperty("washSaleRisk");
+ expect(sim).toHaveProperty("remainingPosition");
+ expect(sim).toHaveProperty("insufficientLots");
+ expect(sim).toHaveProperty("availableAmount");
+ }
+ });
+
+ it("returns all 7 comparable methods in result.methods", () => {
+ const lots = [makeLot("L1", "BTC", 1, 30000, "2024-01-01")];
+ const input: Omit = {
+ asset: "BTC",
+ amount: 1,
+ pricePerUnit: 50000,
+ date: new Date("2025-06-01"),
+ };
+
+ const result = compareAllMethods(lots, input);
+
+ const expectedMethods = [
+ "FIFO",
+ "LIFO",
+ "HIFO",
+ "GERMANY_FIFO",
+ "PMPA",
+ "TOTAL_AVERAGE",
+ "UK_SHARE_POOLING",
+ ];
+ for (const m of expectedMethods) {
+ expect(result.methods).toHaveProperty(m);
}
+ expect(Object.keys(result.methods)).toHaveLength(7);
});
});
diff --git a/packages/tax-engine/src/__tests__/pmpa.test.ts b/packages/tax-engine/src/__tests__/pmpa.test.ts
new file mode 100644
index 00000000..4667935e
--- /dev/null
+++ b/packages/tax-engine/src/__tests__/pmpa.test.ts
@@ -0,0 +1,335 @@
+/**
+ * PMPA (Prix Moyen Pondéré d'Acquisition) Unit Tests
+ *
+ * Tests cover:
+ * 1. Single lot, single sale (avg = individual cost)
+ * 2. Multiple lots at different prices → weighted average cost
+ * 3. Partial sale (verify avg cost is used)
+ * 4. Sequential sales (avg cost recalculates after first sale)
+ * 5. Loss scenario
+ * 6. Fee handling
+ * 7. Holding period (based on earliest consumed lot)
+ * 8. StrictSilo mode
+ *
+ * @license AGPL-3.0
+ */
+
+import { describe, it, expect, vi } from "vitest";
+import { calculatePMPA } from "../methods/pmpa";
+import type { TaxLot, TaxableEvent } from "../types";
+
+// ─── Helpers ────────────────────────────────────────
+
+function createLot(overrides: Partial & { asset: string }): TaxLot {
+ return {
+ id: `lot-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2024-01-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+function createEvent(
+ overrides: Partial & { asset: string },
+): TaxableEvent {
+ return {
+ id: `event-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ proceedsUsd: 40000,
+ date: new Date("2025-06-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+// ─── Tests ──────────────────────────────────────────
+
+describe("calculatePMPA", () => {
+ // ── Test 1: Single lot (avg = individual cost) ────
+ it("should equal individual cost with a single lot", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ expect(result.gainLoss).toBe(15000); // 45000 - 30000
+ expect(result.method).toBe("PMPA");
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].fullyConsumed).toBe(true);
+ });
+
+ // ── Test 2: Multiple lots → weighted average ─────
+ it("should use weighted average cost across multiple lots", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 20000, // $20k/BTC
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 40000, // $40k/BTC
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ // Avg cost = (20000 + 40000) / 2 = $30000/BTC
+ // Gain = 50000 - 30000 = 20000
+ expect(result.gainLoss).toBe(20000);
+ expect(result.matchedLots).toHaveLength(1);
+ // Cost basis in matched lot uses avg cost
+ expect(result.matchedLots[0].costBasisUsd).toBe(30000);
+ });
+
+ // ── Test 3: Partial sale with weighted average ────
+ it("should use weighted average for partial sales", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 5.0,
+ costBasisUsd: 10000, // $2000/ETH
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "ETH",
+ amount: 5.0,
+ costBasisUsd: 20000, // $4000/ETH
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "ETH",
+ amount: 3.0,
+ proceedsUsd: 12000, // $4000/ETH
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ // Avg cost = (10000 + 20000) / 10 = $3000/ETH
+ // Cost basis for 3 ETH = 3000 * 3 = 9000
+ // Gain = 12000 - 9000 = 3000
+ expect(result.gainLoss).toBe(3000);
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].amountConsumed).toBe(3.0);
+ expect(result.matchedLots[0].costBasisUsd).toBe(9000);
+ expect(result.matchedLots[0].fullyConsumed).toBe(false);
+ });
+
+ // ── Test 4: Sequential sales ──────────────────────
+ it("should recalculate average cost after first sale consumes lots", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 20000, // $20k/BTC
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 40000, // $40k/BTC
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ // First sale: sell 1 BTC
+ const event1 = createEvent({
+ id: "sale-1",
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ });
+
+ const result1 = calculatePMPA(lots, event1);
+ // Avg cost = (20k + 40k) / 2 = 30k
+ expect(result1.gainLoss).toBe(20000); // 50000 - 30000
+
+ // After first sale, lot-1 is fully consumed (amount=0)
+ // lot-2 still has 1.0 BTC with costBasis = 40000
+
+ // Second sale: sell remaining 1 BTC
+ const event2 = createEvent({
+ id: "sale-2",
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ });
+
+ const result2 = calculatePMPA(lots, event2);
+ // Now only lot-2 remains: avg cost = 40000 / 1.0 = 40k
+ expect(result2.gainLoss).toBe(10000); // 50000 - 40000
+ });
+
+ // ── Test 5: Loss scenario ─────────────────────────
+ it("should calculate loss when proceeds < weighted avg cost", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 2.0,
+ costBasisUsd: 8000, // $4000/ETH
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "ETH",
+ amount: 2.0,
+ costBasisUsd: 12000, // $6000/ETH
+ acquiredAt: new Date("2024-09-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "ETH",
+ amount: 2.0,
+ proceedsUsd: 6000, // $3000/ETH — a loss
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ // Avg cost = (8000 + 12000) / 4 = $5000/ETH
+ // Cost = 5000 * 2 = 10000
+ // Loss = 6000 - 10000 = -4000
+ expect(result.gainLoss).toBe(-4000);
+ });
+
+ // ── Test 6: Fee handling ──────────────────────────
+ it("should deduct fees from gain calculation", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ feeUsd: 100,
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ // 45000 - 30000 - 100 = 14900
+ expect(result.gainLoss).toBe(14900);
+ });
+
+ // ── Test 7: Holding period ────────────────────────
+ it("should determine holding period from earliest consumed lot", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 15000,
+ acquiredAt: new Date("2023-01-01"), // > 1 year ago
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2025-03-01"), // < 1 year ago
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 0.5,
+ proceedsUsd: 25000,
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculatePMPA(lots, event);
+
+ // FIFO order: lot-1 is consumed first → long-term
+ expect(result.holdingPeriod).toBe("LONG_TERM");
+ });
+
+ // ── Test 8: StrictSilo mode ───────────────────────
+ it("should only match lots from same source in strictSilo mode", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 20000,
+ sourceId: "binance",
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 40000,
+ sourceId: "kraken",
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ sourceId: "kraken",
+ });
+
+ const result = calculatePMPA(lots, event, true);
+
+ // Should only use lot-2 (kraken), avg = 40000/1 = 40000
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].lotId).toBe("lot-2");
+ expect(result.gainLoss).toBe(10000); // 50000 - 40000
+ });
+
+ // ── Test 9: Empty lots ────────────────────────────
+ it("should handle empty lots array", () => {
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ });
+
+ const result = calculatePMPA([], event);
+
+ expect(result.matchedLots).toHaveLength(0);
+ expect(result.gainLoss).toBe(50000); // proceeds - 0 cost
+ expect(consoleSpy).toHaveBeenCalled();
+
+ consoleSpy.mockRestore();
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/reconciliation-covered.test.ts b/packages/tax-engine/src/__tests__/reconciliation-covered.test.ts
new file mode 100644
index 00000000..e89d2c76
--- /dev/null
+++ b/packages/tax-engine/src/__tests__/reconciliation-covered.test.ts
@@ -0,0 +1,165 @@
+import { describe, it, expect } from "vitest";
+import { reconcile } from "../reconciliation/reconciler";
+import type { Form1099DAEntry, DtaxDisposition } from "../reconciliation/types";
+
+function makeBroker(overrides: Partial = {}): Form1099DAEntry {
+ return {
+ rowIndex: 1,
+ asset: "BTC",
+ dateSold: new Date("2026-09-20"),
+ grossProceeds: 50000,
+ ...overrides,
+ };
+}
+
+function makeDtax(overrides: Partial = {}): DtaxDisposition {
+ return {
+ eventId: "e1",
+ asset: "BTC",
+ dateSold: new Date("2026-09-20"),
+ proceeds: 50000,
+ costBasis: 45000,
+ gainLoss: 5000,
+ ...overrides,
+ };
+}
+
+describe("1099-DA Covered vs Noncovered", () => {
+ it("should mark entries as covered when acquired on/after 2026-01-01 with cost basis", () => {
+ const broker = [
+ makeBroker({
+ dateAcquired: new Date("2026-03-15"),
+ costBasis: 45000,
+ gainLoss: 5000,
+ }),
+ ];
+ const dtax = [makeDtax()];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Coinbase",
+ });
+ expect(result.items[0].coverageStatus).toBe("covered");
+ expect(result.summary.coveredCount).toBe(1);
+ expect(result.summary.noncoveredCount).toBe(0);
+ });
+
+ it("should mark entries as noncovered when acquired before 2026-01-01", () => {
+ const broker = [
+ makeBroker({
+ asset: "ETH",
+ dateAcquired: new Date("2024-06-01"),
+ dateSold: new Date("2026-04-10"),
+ grossProceeds: 3000,
+ costBasis: 2000,
+ gainLoss: 1000,
+ }),
+ ];
+ const dtax = [
+ makeDtax({
+ eventId: "e2",
+ asset: "ETH",
+ dateSold: new Date("2026-04-10"),
+ proceeds: 3000,
+ costBasis: 2000,
+ gainLoss: 1000,
+ }),
+ ];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Coinbase",
+ });
+ expect(result.items[0].coverageStatus).toBe("noncovered");
+ expect(result.summary.noncoveredCount).toBe(1);
+ });
+
+ it("should mark entries as noncovered when costBasis is null (transferred-in assets)", () => {
+ const broker = [
+ makeBroker({
+ dateAcquired: new Date("2026-05-01"),
+ costBasis: undefined,
+ }),
+ ];
+ const dtax = [makeDtax()];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Kraken",
+ });
+ expect(result.items[0].coverageStatus).toBe("noncovered");
+ });
+
+ it("should mark entries as noncovered when costBasis is 0", () => {
+ const broker = [
+ makeBroker({
+ dateAcquired: new Date("2026-05-01"),
+ costBasis: 0,
+ }),
+ ];
+ const dtax = [makeDtax()];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Kraken",
+ });
+ expect(result.items[0].coverageStatus).toBe("noncovered");
+ });
+
+ it("should mark entries as noncovered when dateAcquired is missing", () => {
+ const broker = [
+ makeBroker({
+ costBasis: 45000,
+ // no dateAcquired = likely transferred in
+ }),
+ ];
+ const dtax = [makeDtax()];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Gemini",
+ });
+ expect(result.items[0].coverageStatus).toBe("noncovered");
+ });
+
+ it("should mark missing_in_1099da entries as unknown coverage", () => {
+ const broker: Form1099DAEntry[] = [];
+ const dtax = [makeDtax()];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Coinbase",
+ });
+ expect(result.items[0].coverageStatus).toBe("unknown");
+ expect(result.items[0].status).toBe("missing_in_1099da");
+ });
+
+ it("should count covered and noncovered in summary", () => {
+ const broker = [
+ makeBroker({
+ rowIndex: 1,
+ dateAcquired: new Date("2026-03-15"),
+ costBasis: 45000,
+ gainLoss: 5000,
+ }),
+ makeBroker({
+ rowIndex: 2,
+ asset: "ETH",
+ dateAcquired: new Date("2024-01-01"),
+ grossProceeds: 2000,
+ costBasis: 1500,
+ gainLoss: 500,
+ }),
+ ];
+ const dtax = [
+ makeDtax(),
+ makeDtax({
+ eventId: "e2",
+ asset: "ETH",
+ proceeds: 2000,
+ costBasis: 1500,
+ gainLoss: 500,
+ }),
+ ];
+ const result = reconcile(broker, dtax, {
+ taxYear: 2026,
+ brokerName: "Coinbase",
+ });
+ expect(result.summary.coveredCount).toBe(1);
+ expect(result.summary.noncoveredCount).toBe(1);
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/total-average.test.ts b/packages/tax-engine/src/__tests__/total-average.test.ts
new file mode 100644
index 00000000..56ed6f6b
--- /dev/null
+++ b/packages/tax-engine/src/__tests__/total-average.test.ts
@@ -0,0 +1,260 @@
+/**
+ * Total Average (総平均法) Unit Tests
+ *
+ * Tests cover:
+ * 1. Basic weighted average calculation
+ * 2. Multiple lots at different prices
+ * 3. Sequential sales
+ * 4. Empty lots edge case
+ * 5. StrictSilo mode
+ *
+ * @license AGPL-3.0
+ */
+
+import { describe, it, expect, vi } from "vitest";
+import { calculateTotalAverage } from "../methods/total-average";
+import type { TaxLot, TaxableEvent } from "../types";
+
+// ─── Helpers ────────────────────────────────────────
+
+function createLot(overrides: Partial & { asset: string }): TaxLot {
+ return {
+ id: `lot-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ costBasisUsd: 30000,
+ acquiredAt: new Date("2024-01-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+function createEvent(
+ overrides: Partial & { asset: string },
+): TaxableEvent {
+ return {
+ id: `event-${Math.random().toString(36).slice(2, 8)}`,
+ amount: 1.0,
+ proceedsUsd: 40000,
+ date: new Date("2025-06-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+// ─── Tests ──────────────────────────────────────────
+
+describe("calculateTotalAverage", () => {
+ // ── Test 1: Basic weighted average ────────────────
+ it("should calculate gain using weighted average cost", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ });
+
+ const result = calculateTotalAverage(lots, event);
+
+ expect(result.gainLoss).toBe(15000); // 45000 - 30000
+ expect(result.method).toBe("TOTAL_AVERAGE");
+ expect(result.matchedLots).toHaveLength(1);
+ });
+
+ // ── Test 2: Multiple lots, verify average cost ────
+ it("should average cost across multiple lots at different prices", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 3.0,
+ costBasisUsd: 6000, // $2000/ETH
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "ETH",
+ amount: 2.0,
+ costBasisUsd: 8000, // $4000/ETH
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "ETH",
+ amount: 2.0,
+ proceedsUsd: 8000, // $4000/ETH
+ });
+
+ const result = calculateTotalAverage(lots, event);
+
+ // Avg cost = (6000 + 8000) / 5 = $2800/ETH
+ // Cost basis for 2 ETH = 2800 * 2 = 5600
+ // Gain = 8000 - 5600 = 2400
+ expect(result.gainLoss).toBe(2400);
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].costBasisUsd).toBeCloseTo(5600, 2);
+ });
+
+ // ── Test 3: Sequential sales ──────────────────────
+ it("should recalculate average after lots are consumed", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 10000, // $10k/BTC
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000, // $30k/BTC
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ // First sale
+ const event1 = createEvent({
+ id: "sale-1",
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 25000,
+ });
+
+ const result1 = calculateTotalAverage(lots, event1);
+ // Avg = (10k + 30k) / 2 = 20k
+ expect(result1.gainLoss).toBe(5000); // 25000 - 20000
+
+ // After first sale, lot-1 is consumed, lot-2 has 1.0 BTC at $30k
+ const event2 = createEvent({
+ id: "sale-2",
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 35000,
+ });
+
+ const result2 = calculateTotalAverage(lots, event2);
+ // Only lot-2 left: avg = 30000 / 1 = 30k
+ expect(result2.gainLoss).toBe(5000); // 35000 - 30000
+ });
+
+ // ── Test 4: Empty lots edge case ──────────────────
+ it("should handle empty lots array", () => {
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ });
+
+ const result = calculateTotalAverage([], event);
+
+ expect(result.matchedLots).toHaveLength(0);
+ expect(result.holdingPeriod).toBe("SHORT_TERM");
+ expect(consoleSpy).toHaveBeenCalled();
+
+ consoleSpy.mockRestore();
+ });
+
+ // ── Test 5: StrictSilo mode ───────────────────────
+ it("should only match lots from same source in strictSilo mode", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 20000,
+ sourceId: "binance",
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 40000,
+ sourceId: "kraken",
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 50000,
+ sourceId: "binance",
+ });
+
+ const result = calculateTotalAverage(lots, event, true);
+
+ // Should only use lot-1 (binance), avg = 20000
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].lotId).toBe("lot-1");
+ expect(result.gainLoss).toBe(30000); // 50000 - 20000
+ });
+
+ // ── Test 6: Fee handling ──────────────────────────
+ it("should deduct fees from gain calculation", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1.0,
+ costBasisUsd: 30000,
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 1.0,
+ proceedsUsd: 45000,
+ feeUsd: 200,
+ });
+
+ const result = calculateTotalAverage(lots, event);
+
+ // 45000 - 30000 - 200 = 14800
+ expect(result.gainLoss).toBe(14800);
+ });
+
+ // ── Test 7: Holding period based on earliest lot ──
+ it("should determine holding period from earliest consumed lot", () => {
+ const lots = [
+ createLot({
+ id: "lot-1",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2023-01-01"), // > 1 year
+ }),
+ createLot({
+ id: "lot-2",
+ asset: "BTC",
+ amount: 0.5,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2025-03-01"), // < 1 year
+ }),
+ ];
+
+ const event = createEvent({
+ asset: "BTC",
+ amount: 0.5,
+ proceedsUsd: 25000,
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculateTotalAverage(lots, event);
+
+ // FIFO: lot-1 consumed first → long-term
+ expect(result.holdingPeriod).toBe("LONG_TERM");
+ });
+});
diff --git a/packages/tax-engine/src/__tests__/uk-share-pooling.test.ts b/packages/tax-engine/src/__tests__/uk-share-pooling.test.ts
new file mode 100644
index 00000000..26de0b72
--- /dev/null
+++ b/packages/tax-engine/src/__tests__/uk-share-pooling.test.ts
@@ -0,0 +1,386 @@
+/**
+ * UK Share Pooling (HMRC Section 104 Pool) Unit Tests
+ *
+ * Tests cover:
+ * 1. Single lot — pool cost = lot cost
+ * 2. Multiple lots — weighted average pool cost
+ * 3. Partial sale — proportional pool cost
+ * 4. Multiple sequential sales
+ * 5. No matching lots → zero result
+ * 6. Fee handling
+ * 7. Strict silo mode
+ * 8. Long-term holding period
+ * 9. Short-term holding period
+ * 10. Mixed assets — only pool matching asset
+ * 11. Precision with small amounts
+ * 12. Full liquidation
+ * 13. Loss scenario
+ *
+ * @license AGPL-3.0
+ */
+
+import { describe, it, expect, vi } from "vitest";
+import { calculateUKSharePooling } from "../methods/uk-share-pooling";
+import type { TaxLot, TaxableEvent } from "../types";
+
+// ─── Helpers ────────────────────────────────────────
+
+function makeLot(overrides: Partial = {}): TaxLot {
+ return {
+ id: "lot-1",
+ asset: "BTC",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-01-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+function makeEvent(overrides: Partial = {}): TaxableEvent {
+ return {
+ id: "evt-1",
+ asset: "BTC",
+ amount: 1,
+ proceedsUsd: 15000,
+ date: new Date("2024-06-01"),
+ sourceId: "exchange-1",
+ ...overrides,
+ };
+}
+
+// ─── Tests ──────────────────────────────────────────
+
+describe("UK Share Pooling (Section 104)", () => {
+ // 1. Single lot — pool cost = lot cost
+ it("single lot gives exact cost basis", () => {
+ const lots = [makeLot({ id: "lot-1", amount: 1, costBasisUsd: 10000 })];
+ const event = makeEvent({ amount: 1, proceedsUsd: 15000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ expect(result.gainLoss).toBe(5000); // 15000 - 10000
+ expect(result.method).toBe("UK_SHARE_POOLING");
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].fullyConsumed).toBe(true);
+ expect(result.matchedLots[0].costBasisUsd).toBe(10000);
+ });
+
+ // 2. Multiple lots — weighted average pool cost
+ it("pools multiple lots into weighted average", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 1,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2024-03-01"),
+ }),
+ ];
+ const event = makeEvent({ amount: 1, proceedsUsd: 18000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool avg = (10000 + 20000) / 2 = 15000/BTC
+ // Gain = 18000 - 15000 = 3000
+ expect(result.gainLoss).toBe(3000);
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].costBasisUsd).toBe(15000);
+ });
+
+ // 3. Partial sale — proportional pool cost
+ it("handles partial sale with proportional cost", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ asset: "ETH",
+ amount: 5,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ asset: "ETH",
+ amount: 5,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+ const event = makeEvent({ asset: "ETH", amount: 3, proceedsUsd: 12000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool avg = (10000 + 20000) / 10 = 3000/ETH
+ // Cost = 3000 * 3 = 9000
+ // Gain = 12000 - 9000 = 3000
+ expect(result.gainLoss).toBe(3000);
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].amountConsumed).toBe(3);
+ expect(result.matchedLots[0].costBasisUsd).toBe(9000);
+ expect(result.matchedLots[0].fullyConsumed).toBe(false);
+ });
+
+ // 4. Multiple sequential sales
+ it("correctly updates pool after multiple sales", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 1,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 1,
+ costBasisUsd: 40000,
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+
+ // First sale: sell 1 BTC
+ const event1 = makeEvent({ id: "evt-1", amount: 1, proceedsUsd: 50000 });
+ const result1 = calculateUKSharePooling(lots, event1);
+
+ // Pool avg = (20000 + 40000) / 2 = 30000
+ // Gain = 50000 - 30000 = 20000
+ expect(result1.gainLoss).toBe(20000);
+
+ // Second sale: sell remaining 1 BTC (lot-1 consumed, lot-2 remaining)
+ const event2 = makeEvent({ id: "evt-2", amount: 1, proceedsUsd: 50000 });
+ const result2 = calculateUKSharePooling(lots, event2);
+
+ // Only lot-2 remains: avg = 40000/1 = 40000
+ // Gain = 50000 - 40000 = 10000
+ expect(result2.gainLoss).toBe(10000);
+ });
+
+ // 5. No matching lots → zero result
+ it("returns zero when no lots match asset", () => {
+ const consoleSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ const lots = [makeLot({ asset: "ETH", amount: 1, costBasisUsd: 5000 })];
+ const event = makeEvent({ asset: "BTC", amount: 1, proceedsUsd: 15000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ expect(result.matchedLots).toHaveLength(0);
+ expect(result.gainLoss).toBe(15000); // proceeds - 0 cost
+ expect(consoleSpy).toHaveBeenCalled();
+
+ consoleSpy.mockRestore();
+ });
+
+ // 6. Fee handling
+ it("deducts fees from gain", () => {
+ const lots = [makeLot({ amount: 1, costBasisUsd: 10000 })];
+ const event = makeEvent({ amount: 1, proceedsUsd: 15000, feeUsd: 200 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // 15000 - 10000 - 200 = 4800
+ expect(result.gainLoss).toBe(4800);
+ });
+
+ // 7. Strict silo mode
+ it("respects strictSilo flag", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 1,
+ costBasisUsd: 10000,
+ sourceId: "binance",
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 1,
+ costBasisUsd: 30000,
+ sourceId: "kraken",
+ }),
+ ];
+ const event = makeEvent({
+ amount: 1,
+ proceedsUsd: 40000,
+ sourceId: "kraken",
+ });
+
+ const result = calculateUKSharePooling(lots, event, true);
+
+ // Only kraken lot-2: avg = 30000/1 = 30000
+ expect(result.matchedLots).toHaveLength(1);
+ expect(result.matchedLots[0].lotId).toBe("lot-2");
+ expect(result.gainLoss).toBe(10000); // 40000 - 30000
+ });
+
+ // 8. Long-term holding period
+ it("classifies long-term when earliest lot > 1 year", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2023-01-01"), // > 1 year before event
+ }),
+ ];
+ const event = makeEvent({
+ amount: 1,
+ proceedsUsd: 15000,
+ date: new Date("2025-06-01"),
+ });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ expect(result.holdingPeriod).toBe("LONG_TERM");
+ });
+
+ // 9. Short-term holding period
+ it("classifies short-term when lots < 1 year", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 1,
+ costBasisUsd: 10000,
+ acquiredAt: new Date("2024-03-01"),
+ }),
+ ];
+ const event = makeEvent({
+ amount: 1,
+ proceedsUsd: 15000,
+ date: new Date("2024-06-01"),
+ });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ expect(result.holdingPeriod).toBe("SHORT_TERM");
+ });
+
+ // 10. Mixed assets — only pool matching asset
+ it("only pools lots of the same asset", () => {
+ const lots = [
+ makeLot({
+ id: "lot-btc",
+ asset: "BTC",
+ amount: 1,
+ costBasisUsd: 10000,
+ }),
+ makeLot({
+ id: "lot-eth",
+ asset: "ETH",
+ amount: 10,
+ costBasisUsd: 50000,
+ }),
+ makeLot({
+ id: "lot-btc2",
+ asset: "BTC",
+ amount: 1,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2024-03-01"),
+ }),
+ ];
+ const event = makeEvent({ asset: "BTC", amount: 1, proceedsUsd: 18000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool for BTC only: (10000 + 20000) / 2 = 15000/BTC
+ // Gain = 18000 - 15000 = 3000
+ expect(result.gainLoss).toBe(3000);
+ // ETH lot should not be touched
+ expect(lots.find((l) => l.id === "lot-eth")!.amount).toBe(10);
+ });
+
+ // 11. Precision with small amounts
+ it("handles small remainder amounts correctly", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 0.00001,
+ costBasisUsd: 0.5,
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 0.00002,
+ costBasisUsd: 1.2,
+ acquiredAt: new Date("2024-02-01"),
+ }),
+ ];
+ const event = makeEvent({ amount: 0.00001, proceedsUsd: 0.8 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool avg = (0.5 + 1.2) / 0.00003 = 56666.666.../unit
+ // Cost = 56666.666... * 0.00001 ≈ 0.56666...
+ // Gain ≈ 0.8 - 0.56666... ≈ 0.23333...
+ expect(result.gainLoss).toBeCloseTo(0.23333, 4);
+ expect(result.matchedLots).toHaveLength(1);
+ });
+
+ // 12. Full liquidation
+ it("handles full liquidation of all lots", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 2,
+ costBasisUsd: 20000,
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 3,
+ costBasisUsd: 45000,
+ acquiredAt: new Date("2024-03-01"),
+ }),
+ ];
+ const event = makeEvent({ amount: 5, proceedsUsd: 80000 });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool avg = (20000 + 45000) / 5 = 13000/BTC
+ // Cost = 13000 * 5 = 65000
+ // Gain = 80000 - 65000 = 15000
+ expect(result.gainLoss).toBe(15000);
+ expect(result.matchedLots).toHaveLength(2);
+ expect(result.matchedLots[0].fullyConsumed).toBe(true);
+ expect(result.matchedLots[1].fullyConsumed).toBe(true);
+
+ // All lots should be depleted
+ expect(lots[0].amount).toBeCloseTo(0, 8);
+ expect(lots[1].amount).toBeCloseTo(0, 8);
+ });
+
+ // 13. Loss scenario
+ it("correctly calculates losses", () => {
+ const lots = [
+ makeLot({
+ id: "lot-1",
+ amount: 2,
+ costBasisUsd: 8000,
+ asset: "ETH",
+ acquiredAt: new Date("2024-01-01"),
+ }),
+ makeLot({
+ id: "lot-2",
+ amount: 2,
+ costBasisUsd: 12000,
+ asset: "ETH",
+ acquiredAt: new Date("2024-06-01"),
+ }),
+ ];
+ const event = makeEvent({
+ asset: "ETH",
+ amount: 2,
+ proceedsUsd: 6000,
+ });
+
+ const result = calculateUKSharePooling(lots, event);
+
+ // Pool avg = (8000 + 12000) / 4 = 5000/ETH
+ // Cost = 5000 * 2 = 10000
+ // Loss = 6000 - 10000 = -4000
+ expect(result.gainLoss).toBe(-4000);
+ });
+});
diff --git a/packages/tax-engine/src/calculator.ts b/packages/tax-engine/src/calculator.ts
index 6079fbfd..6f76acc5 100644
--- a/packages/tax-engine/src/calculator.ts
+++ b/packages/tax-engine/src/calculator.ts
@@ -1,5 +1,10 @@
/**
* CostBasisCalculator — unified entry point for tax calculations.
+ *
+ * Supports built-in methods (FIFO, LIFO, HIFO, SPECIFIC_ID) and
+ * custom strategies via registerStrategy() for international tax
+ * methods (e.g., weighted average, moving average).
+ *
* @license AGPL-3.0
*/
@@ -7,14 +12,48 @@ import { calculateFIFO } from "./methods/fifo";
import { calculateLIFO } from "./methods/lifo";
import { calculateHIFO } from "./methods/hifo";
import { calculateSpecificId } from "./methods/specific-id";
+import { calculateGermanyFIFO } from "./methods/germany-fifo";
+import { calculatePMPA } from "./methods/pmpa";
+import { calculateTotalAverage } from "./methods/total-average";
+import { calculateUKSharePooling } from "./methods/uk-share-pooling";
import type {
TaxLot,
TaxableEvent,
CalculationResult,
CostBasisMethod,
+ CostBasisStrategy,
LotSelection,
} from "./types";
+/** Global registry of custom strategies */
+const strategyRegistry = new Map();
+
+/**
+ * Register a custom cost basis calculation strategy.
+ *
+ * @example
+ * ```typescript
+ * registerStrategy({
+ * name: "WEIGHTED_AVG",
+ * calculate(lots, event, strictSilo) { ... }
+ * });
+ * const calc = new CostBasisCalculator("WEIGHTED_AVG");
+ * ```
+ */
+export function registerStrategy(strategy: CostBasisStrategy): void {
+ strategyRegistry.set(strategy.name, strategy);
+}
+
+/** Get a registered custom strategy by name */
+export function getStrategy(name: string): CostBasisStrategy | undefined {
+ return strategyRegistry.get(name);
+}
+
+/** List all registered custom strategy names */
+export function getRegisteredStrategies(): string[] {
+ return Array.from(strategyRegistry.keys());
+}
+
export class CostBasisCalculator {
private method: CostBasisMethod;
private lots: TaxLot[] = [];
@@ -40,12 +79,26 @@ export class CostBasisCalculator {
return calculateLIFO(this.lots, event, strictSilo);
case "HIFO":
return calculateHIFO(this.lots, event, strictSilo);
+ case "GERMANY_FIFO":
+ return calculateGermanyFIFO(this.lots, event, strictSilo);
+ case "PMPA":
+ return calculatePMPA(this.lots, event, strictSilo);
+ case "TOTAL_AVERAGE":
+ return calculateTotalAverage(this.lots, event, strictSilo);
+ case "UK_SHARE_POOLING":
+ return calculateUKSharePooling(this.lots, event, strictSilo);
case "SPECIFIC_ID":
throw new Error(
"SPECIFIC_ID requires lot selections — use calculateSpecificId()",
);
- default:
+ default: {
+ // Check custom strategy registry
+ const strategy = strategyRegistry.get(this.method);
+ if (strategy) {
+ return strategy.calculate(this.lots, event, strictSilo);
+ }
throw new Error(`Unknown method: ${this.method}`);
+ }
}
}
diff --git a/packages/tax-engine/src/index.ts b/packages/tax-engine/src/index.ts
index a0db8763..99b4329c 100644
--- a/packages/tax-engine/src/index.ts
+++ b/packages/tax-engine/src/index.ts
@@ -12,12 +12,22 @@ export { calculateFIFO } from "./methods/fifo";
export { calculateLIFO } from "./methods/lifo";
export { calculateHIFO } from "./methods/hifo";
export { calculateSpecificId } from "./methods/specific-id";
-export { CostBasisCalculator } from "./calculator";
+export { calculateGermanyFIFO } from "./methods/germany-fifo";
+export { calculatePMPA } from "./methods/pmpa";
+export { calculateTotalAverage } from "./methods/total-average";
+export { calculateUKSharePooling } from "./methods/uk-share-pooling";
+export {
+ CostBasisCalculator,
+ registerStrategy,
+ getStrategy,
+ getRegisteredStrategies,
+} from "./calculator";
export type {
TaxLot,
TaxableEvent,
CalculationResult,
CostBasisMethod,
+ CostBasisStrategy,
LotSelection,
} from "./types";
@@ -156,3 +166,6 @@ export type {
RiskReport,
RiskScanTransaction,
} from "./risk-scanner";
+
+// Price Provider Interface
+export type { PriceProvider, PricePoint } from "./price-provider";
diff --git a/packages/tax-engine/src/math.ts b/packages/tax-engine/src/math.ts
new file mode 100644
index 00000000..3e126d39
--- /dev/null
+++ b/packages/tax-engine/src/math.ts
@@ -0,0 +1,40 @@
+/**
+ * Decimal-precision arithmetic helpers for tax calculations.
+ *
+ * Wraps decimal.js to provide exact arithmetic for financial computations.
+ * All public functions accept and return JavaScript `number`, performing
+ * conversions at the boundary so call sites stay readable.
+ *
+ * @license AGPL-3.0
+ */
+
+import Decimal from "decimal.js";
+
+// Configure Decimal for financial calculations: 20 significant digits, ROUND_HALF_UP
+Decimal.set({ precision: 20, rounding: Decimal.ROUND_HALF_UP });
+
+/** Add two financial values without floating-point drift. */
+export function dadd(a: number, b: number): number {
+ return new Decimal(a).plus(new Decimal(b)).toNumber();
+}
+
+/** Subtract two financial values without floating-point drift. */
+export function dsub(a: number, b: number): number {
+ return new Decimal(a).minus(new Decimal(b)).toNumber();
+}
+
+/** Multiply two financial values without floating-point drift. */
+export function dmul(a: number, b: number): number {
+ return new Decimal(a).times(new Decimal(b)).toNumber();
+}
+
+/** Divide two financial values without floating-point drift. Returns 0 if divisor is 0. */
+export function ddiv(a: number, b: number): number {
+ if (b === 0) return 0;
+ return new Decimal(a).dividedBy(new Decimal(b)).toNumber();
+}
+
+/** Check if a value is effectively zero (within crypto dust threshold). */
+export function isEffectivelyZero(a: number, epsilon = 1e-8): boolean {
+ return Math.abs(a) < epsilon;
+}
diff --git a/packages/tax-engine/src/methods/fifo.ts b/packages/tax-engine/src/methods/fifo.ts
index f9024d12..91faf3dc 100644
--- a/packages/tax-engine/src/methods/fifo.ts
+++ b/packages/tax-engine/src/methods/fifo.ts
@@ -12,18 +12,9 @@ import type {
TaxableEvent,
CalculationResult,
MatchedLot,
- HoldingPeriod,
} from "../types";
-
-const ONE_YEAR_MS = 365.25 * 24 * 60 * 60 * 1000;
-
-/**
- * Determine holding period based on acquisition and sale dates.
- */
-function getHoldingPeriod(acquiredAt: Date, soldAt: Date): HoldingPeriod {
- const holdingMs = soldAt.getTime() - acquiredAt.getTime();
- return holdingMs >= ONE_YEAR_MS ? "LONG_TERM" : "SHORT_TERM";
-}
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
/**
* Calculate capital gains/losses using the FIFO method.
@@ -54,7 +45,9 @@ export function calculateFIFO(
// Sort lots by acquisition date (ascending) for FIFO
const sortedLots = [...applicableLots]
- .filter((lot) => lot.asset === event.asset && lot.amount > 0.00000001)
+ .filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ )
.sort((a, b) => a.acquiredAt.getTime() - b.acquiredAt.getTime());
let remainingAmount = event.amount;
@@ -63,13 +56,12 @@ export function calculateFIFO(
let earliestLotDate: Date | null = null;
for (const lot of sortedLots) {
- if (remainingAmount <= 0) break;
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
const consumeAmount = Math.min(lot.amount, remainingAmount);
- const costPerUnit =
- lot.amount > 0.00000001 ? lot.costBasisUsd / lot.amount : 0;
- const consumedCostBasis = costPerUnit * consumeAmount;
- const fullyConsumed = consumeAmount >= lot.amount - 0.00000001;
+ const costPerUnit = ddiv(lot.costBasisUsd, lot.amount);
+ const consumedCostBasis = dmul(costPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
matchedLots.push({
lotId: lot.id,
@@ -79,26 +71,25 @@ export function calculateFIFO(
});
// Mutate lot to track remaining balance across multiple calculations
- lot.amount -= consumeAmount;
- lot.costBasisUsd -= consumedCostBasis;
- totalCostBasis += consumedCostBasis;
- remainingAmount -= consumeAmount;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(lot.costBasisUsd, consumedCostBasis);
+ totalCostBasis = dadd(totalCostBasis, consumedCostBasis);
+ remainingAmount = dsub(remainingAmount, consumeAmount);
if (!earliestLotDate) {
earliestLotDate = lot.acquiredAt;
}
}
- if (remainingAmount > 0.00000001) {
- // Floating point tolerance
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
console.warn(
`[DTax FIFO] Insufficient lots for ${event.asset}: ` +
- `needed ${event.amount}, matched ${event.amount - remainingAmount}`,
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
);
}
const feeUsd = event.feeUsd ?? 0;
- const gainLoss = event.proceedsUsd - totalCostBasis - feeUsd;
+ const gainLoss = dsub(dsub(event.proceedsUsd, totalCostBasis), feeUsd);
const holdingPeriod = earliestLotDate
? getHoldingPeriod(earliestLotDate, event.date)
: "SHORT_TERM";
diff --git a/packages/tax-engine/src/methods/germany-fifo.ts b/packages/tax-engine/src/methods/germany-fifo.ts
new file mode 100644
index 00000000..cebcd3e6
--- /dev/null
+++ b/packages/tax-engine/src/methods/germany-fifo.ts
@@ -0,0 +1,123 @@
+/**
+ * Germany FIFO with 12-Month Tax Exemption (§23 EStG Spekulationsfrist).
+ *
+ * Uses FIFO lot ordering (earliest acquired first), but gains from lots
+ * held longer than 12 months (365.25 days) are tax-exempt. Losses from
+ * exempt lots are also not deductible.
+ *
+ * @license AGPL-3.0
+ */
+
+import type {
+ TaxLot,
+ TaxableEvent,
+ CalculationResult,
+ MatchedLot,
+} from "../types";
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
+
+/**
+ * Check if a lot qualifies for Germany's 12-month tax exemption.
+ */
+function isExempt(acquiredAt: Date, soldAt: Date): boolean {
+ // German 1-year holding exemption: held more than 1 year
+ const dayAfter = new Date(acquiredAt);
+ dayAfter.setDate(dayAfter.getDate() + 1);
+ const oneYearLater = new Date(dayAfter);
+ oneYearLater.setFullYear(oneYearLater.getFullYear() + 1);
+ return soldAt >= oneYearLater;
+}
+
+/**
+ * Calculate capital gains/losses using Germany FIFO with 12-month exemption.
+ *
+ * Lots held > 12 months have their gain/loss zeroed out (tax-free under
+ * §23 EStG). Lots are still consumed normally for tracking purposes.
+ *
+ * @param lots - Available tax lots
+ * @param event - The taxable event (sale/trade)
+ * @param strictSilo - If true, only match lots with same sourceId
+ * @returns CalculationResult with gains/losses (exempt portions excluded)
+ */
+export function calculateGermanyFIFO(
+ lots: TaxLot[],
+ event: TaxableEvent,
+ strictSilo: boolean = false,
+): CalculationResult {
+ const applicableLots = strictSilo
+ ? lots.filter((l) => l.sourceId === event.sourceId)
+ : lots;
+
+ // Sort lots by acquisition date (ascending) for FIFO
+ const sortedLots = [...applicableLots]
+ .filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ )
+ .sort((a, b) => a.acquiredAt.getTime() - b.acquiredAt.getTime());
+
+ let remainingAmount = event.amount;
+ let taxableCostBasis = 0;
+ let taxableProceeds = 0;
+ const matchedLots: MatchedLot[] = [];
+ let earliestLotDate: Date | null = null;
+
+ for (const lot of sortedLots) {
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
+
+ const consumeAmount = Math.min(lot.amount, remainingAmount);
+ const costPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ const consumedCostBasis = dmul(costPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
+
+ matchedLots.push({
+ lotId: lot.id,
+ amountConsumed: consumeAmount,
+ costBasisUsd: consumedCostBasis,
+ fullyConsumed,
+ });
+
+ // Mutate lot to track remaining balance
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(lot.costBasisUsd, consumedCostBasis);
+ remainingAmount = dsub(remainingAmount, consumeAmount);
+
+ // Only count toward taxable gain if held <= 12 months
+ if (!isExempt(lot.acquiredAt, event.date)) {
+ taxableCostBasis = dadd(taxableCostBasis, consumedCostBasis);
+ // Proportional proceeds for this lot portion
+ const portionProceeds = dmul(
+ ddiv(consumeAmount, event.amount),
+ event.proceedsUsd,
+ );
+ taxableProceeds = dadd(taxableProceeds, portionProceeds);
+ }
+
+ if (!earliestLotDate) {
+ earliestLotDate = lot.acquiredAt;
+ }
+ }
+
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
+ console.warn(
+ `[DTax GERMANY_FIFO] Insufficient lots for ${event.asset}: ` +
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
+ );
+ }
+
+ const feeUsd = event.feeUsd ?? 0;
+ const gainLoss = dsub(dsub(taxableProceeds, taxableCostBasis), feeUsd);
+ const holdingPeriod = earliestLotDate
+ ? getHoldingPeriod(earliestLotDate, event.date)
+ : "SHORT_TERM";
+
+ return {
+ event,
+ matchedLots,
+ gainLoss,
+ holdingPeriod,
+ method: "GERMANY_FIFO",
+ };
+}
diff --git a/packages/tax-engine/src/methods/hifo.ts b/packages/tax-engine/src/methods/hifo.ts
index ebe636c5..6bfd0ae6 100644
--- a/packages/tax-engine/src/methods/hifo.ts
+++ b/packages/tax-engine/src/methods/hifo.ts
@@ -16,15 +16,9 @@ import type {
TaxableEvent,
CalculationResult,
MatchedLot,
- HoldingPeriod,
} from "../types";
-
-const ONE_YEAR_MS = 365.25 * 24 * 60 * 60 * 1000;
-
-function getHoldingPeriod(acquiredAt: Date, soldAt: Date): HoldingPeriod {
- const holdingMs = soldAt.getTime() - acquiredAt.getTime();
- return holdingMs >= ONE_YEAR_MS ? "LONG_TERM" : "SHORT_TERM";
-}
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
/**
* Calculate capital gains/losses using the HIFO method.
@@ -42,14 +36,13 @@ export function calculateHIFO(
? lots.filter((l) => l.sourceId === event.sourceId)
: lots;
- // Sort lots by cost per unit DESCENDING (highest cost first)
+ // Sort by cost-per-unit DESCENDING. Native division is sufficient for ordering;
+ // exact Decimal arithmetic is reserved for the financial mutations below.
const sortedLots = [...applicableLots]
- .filter((lot) => lot.asset === event.asset && lot.amount > 0.00000001)
- .sort((a, b) => {
- const costPerUnitA = a.costBasisUsd / a.amount;
- const costPerUnitB = b.costBasisUsd / b.amount;
- return costPerUnitB - costPerUnitA;
- });
+ .filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ )
+ .sort((a, b) => b.costBasisUsd / b.amount - a.costBasisUsd / a.amount);
let remainingAmount = event.amount;
let totalCostBasis = 0;
@@ -57,13 +50,14 @@ export function calculateHIFO(
let earliestMatchedDate: Date | null = null;
for (const lot of sortedLots) {
- if (remainingAmount <= 0) break;
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
const consumeAmount = Math.min(lot.amount, remainingAmount);
- const costPerUnit =
- lot.amount > 0.00000001 ? lot.costBasisUsd / lot.amount : 0;
- const consumedCostBasis = costPerUnit * consumeAmount;
- const fullyConsumed = consumeAmount >= lot.amount - 0.00000001;
+ const costPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ const consumedCostBasis = dmul(costPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
matchedLots.push({
lotId: lot.id,
@@ -73,10 +67,10 @@ export function calculateHIFO(
});
// Mutate lot to track remaining balance across multiple calculations
- lot.amount -= consumeAmount;
- lot.costBasisUsd -= consumedCostBasis;
- totalCostBasis += consumedCostBasis;
- remainingAmount -= consumeAmount;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(lot.costBasisUsd, consumedCostBasis);
+ totalCostBasis = dadd(totalCostBasis, consumedCostBasis);
+ remainingAmount = dsub(remainingAmount, consumeAmount);
// Track the earliest matched lot for holding period
if (!earliestMatchedDate || lot.acquiredAt < earliestMatchedDate) {
@@ -84,15 +78,15 @@ export function calculateHIFO(
}
}
- if (remainingAmount > 0.00000001) {
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
console.warn(
`[DTax HIFO] Insufficient lots for ${event.asset}: ` +
- `needed ${event.amount}, matched ${event.amount - remainingAmount}`,
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
);
}
const feeUsd = event.feeUsd ?? 0;
- const gainLoss = event.proceedsUsd - totalCostBasis - feeUsd;
+ const gainLoss = dsub(dsub(event.proceedsUsd, totalCostBasis), feeUsd);
const holdingPeriod = earliestMatchedDate
? getHoldingPeriod(earliestMatchedDate, event.date)
: "SHORT_TERM";
diff --git a/packages/tax-engine/src/methods/lifo.ts b/packages/tax-engine/src/methods/lifo.ts
index 905002e3..6ec42f1b 100644
--- a/packages/tax-engine/src/methods/lifo.ts
+++ b/packages/tax-engine/src/methods/lifo.ts
@@ -13,15 +13,9 @@ import type {
TaxableEvent,
CalculationResult,
MatchedLot,
- HoldingPeriod,
} from "../types";
-
-const ONE_YEAR_MS = 365.25 * 24 * 60 * 60 * 1000;
-
-function getHoldingPeriod(acquiredAt: Date, soldAt: Date): HoldingPeriod {
- const holdingMs = soldAt.getTime() - acquiredAt.getTime();
- return holdingMs >= ONE_YEAR_MS ? "LONG_TERM" : "SHORT_TERM";
-}
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
/**
* Calculate capital gains/losses using the LIFO method.
@@ -41,7 +35,9 @@ export function calculateLIFO(
// Sort lots by acquisition date DESCENDING for LIFO (newest first)
const sortedLots = [...applicableLots]
- .filter((lot) => lot.asset === event.asset && lot.amount > 0.00000001)
+ .filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ )
.sort((a, b) => b.acquiredAt.getTime() - a.acquiredAt.getTime());
let remainingAmount = event.amount;
@@ -50,13 +46,14 @@ export function calculateLIFO(
let earliestMatchedDate: Date | null = null;
for (const lot of sortedLots) {
- if (remainingAmount <= 0) break;
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
const consumeAmount = Math.min(lot.amount, remainingAmount);
- const costPerUnit =
- lot.amount > 0.00000001 ? lot.costBasisUsd / lot.amount : 0;
- const consumedCostBasis = costPerUnit * consumeAmount;
- const fullyConsumed = consumeAmount >= lot.amount - 0.00000001;
+ const costPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ const consumedCostBasis = dmul(costPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
matchedLots.push({
lotId: lot.id,
@@ -66,10 +63,10 @@ export function calculateLIFO(
});
// Mutate lot to track remaining balance across multiple calculations
- lot.amount -= consumeAmount;
- lot.costBasisUsd -= consumedCostBasis;
- totalCostBasis += consumedCostBasis;
- remainingAmount -= consumeAmount;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(lot.costBasisUsd, consumedCostBasis);
+ totalCostBasis = dadd(totalCostBasis, consumedCostBasis);
+ remainingAmount = dsub(remainingAmount, consumeAmount);
// Track the earliest matched lot for holding period
if (!earliestMatchedDate || lot.acquiredAt < earliestMatchedDate) {
@@ -77,15 +74,15 @@ export function calculateLIFO(
}
}
- if (remainingAmount > 0.00000001) {
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
console.warn(
`[DTax LIFO] Insufficient lots for ${event.asset}: ` +
- `needed ${event.amount}, matched ${event.amount - remainingAmount}`,
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
);
}
const feeUsd = event.feeUsd ?? 0;
- const gainLoss = event.proceedsUsd - totalCostBasis - feeUsd;
+ const gainLoss = dsub(dsub(event.proceedsUsd, totalCostBasis), feeUsd);
const holdingPeriod = earliestMatchedDate
? getHoldingPeriod(earliestMatchedDate, event.date)
: "SHORT_TERM";
diff --git a/packages/tax-engine/src/methods/pmpa.ts b/packages/tax-engine/src/methods/pmpa.ts
new file mode 100644
index 00000000..652d4adb
--- /dev/null
+++ b/packages/tax-engine/src/methods/pmpa.ts
@@ -0,0 +1,123 @@
+/**
+ * PMPA (Prix Moyen Pondéré d'Acquisition) — French Weighted Average Cost Method.
+ *
+ * Cost basis is calculated as the weighted average of ALL remaining lots,
+ * not individual lot costs. Lots are consumed in FIFO order for tracking.
+ *
+ * @license AGPL-3.0
+ */
+
+import type {
+ TaxLot,
+ TaxableEvent,
+ CalculationResult,
+ MatchedLot,
+} from "../types";
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
+
+/**
+ * Calculate capital gains/losses using the PMPA weighted average method.
+ *
+ * Formula: avgCostPerUnit = totalCostBasis / totalAmount (across all remaining lots)
+ * Gain = proceedsUsd - (avgCostPerUnit × amountSold) - feeUsd
+ *
+ * @param lots - Available tax lots
+ * @param event - The taxable event (sale/trade)
+ * @param strictSilo - If true, only match lots with same sourceId
+ * @returns CalculationResult with gains/losses using weighted average cost
+ */
+export function calculatePMPA(
+ lots: TaxLot[],
+ event: TaxableEvent,
+ strictSilo: boolean = false,
+): CalculationResult {
+ const applicableLots = strictSilo
+ ? lots.filter((l) => l.sourceId === event.sourceId)
+ : lots;
+
+ // Filter to matching asset with remaining balance
+ const assetLots = applicableLots.filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ );
+
+ // Calculate weighted average cost per unit across ALL remaining lots
+ let totalAmount = 0;
+ let totalCostBasis = 0;
+ for (const lot of assetLots) {
+ totalAmount = dadd(totalAmount, lot.amount);
+ totalCostBasis = dadd(totalCostBasis, lot.costBasisUsd);
+ }
+
+ const avgCostPerUnit = !isEffectivelyZero(totalAmount)
+ ? ddiv(totalCostBasis, totalAmount)
+ : 0;
+
+ // Sort lots by acquisition date (ascending) for FIFO consumption
+ const sortedLots = [...assetLots].sort(
+ (a, b) => a.acquiredAt.getTime() - b.acquiredAt.getTime(),
+ );
+
+ let remainingAmount = event.amount;
+ const matchedLots: MatchedLot[] = [];
+ let earliestLotDate: Date | null = null;
+
+ for (const lot of sortedLots) {
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
+
+ const consumeAmount = Math.min(lot.amount, remainingAmount);
+ // Use weighted average cost, not individual lot cost
+ const consumedCostBasis = dmul(avgCostPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
+
+ matchedLots.push({
+ lotId: lot.id,
+ amountConsumed: consumeAmount,
+ costBasisUsd: consumedCostBasis,
+ fullyConsumed,
+ });
+
+ // Mutate lot to track remaining balance
+ const actualCostPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(
+ lot.costBasisUsd,
+ dmul(actualCostPerUnit, consumeAmount),
+ );
+ remainingAmount = dsub(remainingAmount, consumeAmount);
+
+ if (!earliestLotDate) {
+ earliestLotDate = lot.acquiredAt;
+ }
+ }
+
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
+ console.warn(
+ `[DTax PMPA] Insufficient lots for ${event.asset}: ` +
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
+ );
+ }
+
+ const totalConsumedCostBasis = dmul(
+ avgCostPerUnit,
+ dsub(event.amount, remainingAmount),
+ );
+ const feeUsd = event.feeUsd ?? 0;
+ const gainLoss = dsub(
+ dsub(event.proceedsUsd, totalConsumedCostBasis),
+ feeUsd,
+ );
+ const holdingPeriod = earliestLotDate
+ ? getHoldingPeriod(earliestLotDate, event.date)
+ : "SHORT_TERM";
+
+ return {
+ event,
+ matchedLots,
+ gainLoss,
+ holdingPeriod,
+ method: "PMPA",
+ };
+}
diff --git a/packages/tax-engine/src/methods/shared.ts b/packages/tax-engine/src/methods/shared.ts
new file mode 100644
index 00000000..82abb0f9
--- /dev/null
+++ b/packages/tax-engine/src/methods/shared.ts
@@ -0,0 +1,21 @@
+/**
+ * Shared helpers for cost basis calculation methods.
+ * @license AGPL-3.0
+ */
+
+import type { HoldingPeriod } from "../types";
+
+/**
+ * Determine holding period using IRS calendar-based rule.
+ * Long-term = held more than one year from the day after acquisition.
+ */
+export function getHoldingPeriod(
+ acquiredAt: Date,
+ soldAt: Date,
+): HoldingPeriod {
+ const dayAfter = new Date(acquiredAt);
+ dayAfter.setDate(dayAfter.getDate() + 1);
+ const oneYearLater = new Date(dayAfter);
+ oneYearLater.setFullYear(oneYearLater.getFullYear() + 1);
+ return soldAt >= oneYearLater ? "LONG_TERM" : "SHORT_TERM";
+}
diff --git a/packages/tax-engine/src/methods/specific-id.ts b/packages/tax-engine/src/methods/specific-id.ts
index 8d518be4..d33e486e 100644
--- a/packages/tax-engine/src/methods/specific-id.ts
+++ b/packages/tax-engine/src/methods/specific-id.ts
@@ -13,16 +13,10 @@ import type {
TaxableEvent,
CalculationResult,
MatchedLot,
- HoldingPeriod,
LotSelection,
} from "../types";
-
-const ONE_YEAR_MS = 365.25 * 24 * 60 * 60 * 1000;
-
-function getHoldingPeriod(acquiredAt: Date, soldAt: Date): HoldingPeriod {
- const holdingMs = soldAt.getTime() - acquiredAt.getTime();
- return holdingMs >= ONE_YEAR_MS ? "LONG_TERM" : "SHORT_TERM";
-}
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
/**
* Calculate capital gains/losses using the Specific ID method.
@@ -53,17 +47,21 @@ export function calculateSpecificId(
`Lot ${sel.lotId} asset ${lot.asset} does not match event asset ${event.asset}`,
);
}
- if (sel.amount > lot.amount + 0.00000001) {
+ if (
+ sel.amount > lot.amount &&
+ !isEffectivelyZero(dsub(sel.amount, lot.amount))
+ ) {
throw new Error(
`Lot ${sel.lotId} has ${lot.amount} available, requested ${sel.amount}`,
);
}
const consumeAmount = Math.min(sel.amount, lot.amount);
- const costPerUnit =
- lot.amount > 0.00000001 ? lot.costBasisUsd / lot.amount : 0;
- const consumedCostBasis = costPerUnit * consumeAmount;
- const fullyConsumed = consumeAmount >= lot.amount - 0.00000001;
+ const costPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ const consumedCostBasis = dmul(costPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
matchedLots.push({
lotId: lot.id,
@@ -72,24 +70,24 @@ export function calculateSpecificId(
fullyConsumed,
});
- lot.amount -= consumeAmount;
- lot.costBasisUsd -= consumedCostBasis;
- totalCostBasis += consumedCostBasis;
- totalSelected += consumeAmount;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(lot.costBasisUsd, consumedCostBasis);
+ totalCostBasis = dadd(totalCostBasis, consumedCostBasis);
+ totalSelected = dadd(totalSelected, consumeAmount);
if (!earliestLotDate || lot.acquiredAt < earliestLotDate) {
earliestLotDate = lot.acquiredAt;
}
}
- if (Math.abs(totalSelected - event.amount) > 0.00000001) {
+ if (!isEffectivelyZero(dsub(totalSelected, event.amount))) {
throw new Error(
`Selected amount ${totalSelected} does not match event amount ${event.amount}`,
);
}
const feeUsd = event.feeUsd ?? 0;
- const gainLoss = event.proceedsUsd - totalCostBasis - feeUsd;
+ const gainLoss = dsub(dsub(event.proceedsUsd, totalCostBasis), feeUsd);
const holdingPeriod = earliestLotDate
? getHoldingPeriod(earliestLotDate, event.date)
: "SHORT_TERM";
diff --git a/packages/tax-engine/src/methods/total-average.ts b/packages/tax-engine/src/methods/total-average.ts
new file mode 100644
index 00000000..8ac8b8a0
--- /dev/null
+++ b/packages/tax-engine/src/methods/total-average.ts
@@ -0,0 +1,125 @@
+/**
+ * Total Average (総平均法) — Japanese Cost Basis Method.
+ *
+ * All lots for an asset are averaged together to determine cost per unit.
+ * Lots are consumed in FIFO order for tracking purposes.
+ * In practice, Japan recalculates at year-end, but for per-event
+ * calculation the logic is identical to weighted average.
+ *
+ * @license AGPL-3.0
+ */
+
+import type {
+ TaxLot,
+ TaxableEvent,
+ CalculationResult,
+ MatchedLot,
+} from "../types";
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
+
+/**
+ * Calculate capital gains/losses using the Total Average method.
+ *
+ * Formula: avgCostPerUnit = sum(costBasisUsd) / sum(amount) across all lots
+ * Gain = proceedsUsd - (avgCostPerUnit × amountSold) - feeUsd
+ *
+ * @param lots - Available tax lots
+ * @param event - The taxable event (sale/trade)
+ * @param strictSilo - If true, only match lots with same sourceId
+ * @returns CalculationResult with gains/losses using total average cost
+ */
+export function calculateTotalAverage(
+ lots: TaxLot[],
+ event: TaxableEvent,
+ strictSilo: boolean = false,
+): CalculationResult {
+ const applicableLots = strictSilo
+ ? lots.filter((l) => l.sourceId === event.sourceId)
+ : lots;
+
+ // Filter to matching asset with remaining balance
+ const assetLots = applicableLots.filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ );
+
+ // Calculate total average cost per unit across ALL remaining lots
+ let totalAmount = 0;
+ let totalCostBasis = 0;
+ for (const lot of assetLots) {
+ totalAmount = dadd(totalAmount, lot.amount);
+ totalCostBasis = dadd(totalCostBasis, lot.costBasisUsd);
+ }
+
+ const avgCostPerUnit = !isEffectivelyZero(totalAmount)
+ ? ddiv(totalCostBasis, totalAmount)
+ : 0;
+
+ // Sort lots by acquisition date (ascending) for FIFO consumption
+ const sortedLots = [...assetLots].sort(
+ (a, b) => a.acquiredAt.getTime() - b.acquiredAt.getTime(),
+ );
+
+ let remainingAmount = event.amount;
+ const matchedLots: MatchedLot[] = [];
+ let earliestLotDate: Date | null = null;
+
+ for (const lot of sortedLots) {
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
+
+ const consumeAmount = Math.min(lot.amount, remainingAmount);
+ // Use total average cost, not individual lot cost
+ const consumedCostBasis = dmul(avgCostPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
+
+ matchedLots.push({
+ lotId: lot.id,
+ amountConsumed: consumeAmount,
+ costBasisUsd: consumedCostBasis,
+ fullyConsumed,
+ });
+
+ // Mutate lot to track remaining balance
+ const actualCostPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(
+ lot.costBasisUsd,
+ dmul(actualCostPerUnit, consumeAmount),
+ );
+ remainingAmount = dsub(remainingAmount, consumeAmount);
+
+ if (!earliestLotDate) {
+ earliestLotDate = lot.acquiredAt;
+ }
+ }
+
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
+ console.warn(
+ `[DTax TOTAL_AVERAGE] Insufficient lots for ${event.asset}: ` +
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
+ );
+ }
+
+ const totalConsumedCostBasis = dmul(
+ avgCostPerUnit,
+ dsub(event.amount, remainingAmount),
+ );
+ const feeUsd = event.feeUsd ?? 0;
+ const gainLoss = dsub(
+ dsub(event.proceedsUsd, totalConsumedCostBasis),
+ feeUsd,
+ );
+ const holdingPeriod = earliestLotDate
+ ? getHoldingPeriod(earliestLotDate, event.date)
+ : "SHORT_TERM";
+
+ return {
+ event,
+ matchedLots,
+ gainLoss,
+ holdingPeriod,
+ method: "TOTAL_AVERAGE",
+ };
+}
diff --git a/packages/tax-engine/src/methods/uk-share-pooling.ts b/packages/tax-engine/src/methods/uk-share-pooling.ts
new file mode 100644
index 00000000..f3e9217c
--- /dev/null
+++ b/packages/tax-engine/src/methods/uk-share-pooling.ts
@@ -0,0 +1,128 @@
+/**
+ * UK Share Pooling (HMRC Section 104 Pool).
+ *
+ * Cost basis is the weighted average of ALL remaining holdings of the same
+ * asset (the "Section 104 pool"). Individual lot costs are replaced by the
+ * pool average. Lots are consumed FIFO for tracking purposes.
+ *
+ * Note: Same-day and Bed & Breakfast (30-day) matching rules are tracked
+ * but not enforced in this version — they would require event-level lookahead
+ * across the full tax year, which is a future enhancement.
+ *
+ * @license AGPL-3.0
+ */
+
+import type {
+ TaxLot,
+ TaxableEvent,
+ CalculationResult,
+ MatchedLot,
+} from "../types";
+import { getHoldingPeriod } from "./shared";
+import { dadd, dsub, dmul, ddiv, isEffectivelyZero } from "../math";
+
+/**
+ * Calculate capital gains/losses using UK Share Pooling (Section 104).
+ *
+ * Formula: avgCostPerUnit = totalPoolCost / totalPoolQuantity
+ * Gain = proceedsUsd - (avgCostPerUnit × amountSold) - feeUsd
+ *
+ * @param lots - Available tax lots (the Section 104 pool)
+ * @param event - The taxable event (disposal)
+ * @param strictSilo - If true, only match lots with same sourceId
+ * @returns CalculationResult with gains/losses using pooled average cost
+ */
+export function calculateUKSharePooling(
+ lots: TaxLot[],
+ event: TaxableEvent,
+ strictSilo: boolean = false,
+): CalculationResult {
+ const applicableLots = strictSilo
+ ? lots.filter((l) => l.sourceId === event.sourceId)
+ : lots;
+
+ // Filter to matching asset with remaining balance
+ const assetLots = applicableLots.filter(
+ (lot) => lot.asset === event.asset && !isEffectivelyZero(lot.amount),
+ );
+
+ // Calculate Section 104 pool: weighted average cost per unit across ALL lots
+ let totalAmount = 0;
+ let totalCostBasis = 0;
+ for (const lot of assetLots) {
+ totalAmount = dadd(totalAmount, lot.amount);
+ totalCostBasis = dadd(totalCostBasis, lot.costBasisUsd);
+ }
+
+ const avgCostPerUnit = !isEffectivelyZero(totalAmount)
+ ? ddiv(totalCostBasis, totalAmount)
+ : 0;
+
+ // Sort lots by acquisition date (ascending) for FIFO consumption
+ const sortedLots = [...assetLots].sort(
+ (a, b) => a.acquiredAt.getTime() - b.acquiredAt.getTime(),
+ );
+
+ let remainingAmount = event.amount;
+ const matchedLots: MatchedLot[] = [];
+ let earliestLotDate: Date | null = null;
+
+ for (const lot of sortedLots) {
+ if (isEffectivelyZero(remainingAmount) || remainingAmount < 0) break;
+
+ const consumeAmount = Math.min(lot.amount, remainingAmount);
+ // Use pooled average cost, not individual lot cost
+ const consumedCostBasis = dmul(avgCostPerUnit, consumeAmount);
+ const fullyConsumed = isEffectivelyZero(dsub(lot.amount, consumeAmount));
+
+ matchedLots.push({
+ lotId: lot.id,
+ amountConsumed: consumeAmount,
+ costBasisUsd: consumedCostBasis,
+ fullyConsumed,
+ });
+
+ // Mutate lot to track remaining balance
+ const actualCostPerUnit = !isEffectivelyZero(lot.amount)
+ ? ddiv(lot.costBasisUsd, lot.amount)
+ : 0;
+ lot.amount = dsub(lot.amount, consumeAmount);
+ lot.costBasisUsd = dsub(
+ lot.costBasisUsd,
+ dmul(actualCostPerUnit, consumeAmount),
+ );
+ remainingAmount = dsub(remainingAmount, consumeAmount);
+
+ if (!earliestLotDate) {
+ earliestLotDate = lot.acquiredAt;
+ }
+ }
+
+ if (!isEffectivelyZero(remainingAmount) && remainingAmount > 0) {
+ console.warn(
+ `[DTax UK Share Pooling] Insufficient lots for ${event.asset}: ` +
+ `needed ${event.amount}, matched ${dsub(event.amount, remainingAmount)}`,
+ );
+ }
+
+ const totalConsumedCostBasis = dmul(
+ avgCostPerUnit,
+ dsub(event.amount, remainingAmount),
+ );
+ const feeUsd = event.feeUsd ?? 0;
+ const gainLoss = dsub(
+ dsub(event.proceedsUsd, totalConsumedCostBasis),
+ feeUsd,
+ );
+ const holdingPeriod = earliestLotDate
+ ? getHoldingPeriod(earliestLotDate, event.date)
+ : "SHORT_TERM";
+
+ return {
+ event,
+ matchedLots,
+ gainLoss,
+ holdingPeriod,
+ method: "UK_SHARE_POOLING",
+ };
+}
diff --git a/packages/tax-engine/src/normalizers/wrap-unwrap.ts b/packages/tax-engine/src/normalizers/wrap-unwrap.ts
index 63d7e645..88938439 100644
--- a/packages/tax-engine/src/normalizers/wrap-unwrap.ts
+++ b/packages/tax-engine/src/normalizers/wrap-unwrap.ts
@@ -100,16 +100,16 @@ export function processWrapUnwrap(
for (const lot of sourceLots) {
if (remaining <= 0) break;
- const consumed = Math.min(lot.amount, remaining);
- const ratio = consumed / lot.amount;
+ const originalAmount = lot.amount;
+ const consumed = Math.min(originalAmount, remaining);
+ const ratio = consumed / originalAmount;
const basisConsumed = lot.costBasisUsd * ratio;
// Mutate the original lot (same pattern as calculator.ts)
lot.amount -= consumed;
lot.costBasisUsd -= basisConsumed;
- if (consumed === lot.amount + consumed) {
- // Fully consumed (original amount was exactly consumed)
+ if (consumed >= originalAmount - 0.00000001) {
consumedLotIds.push(lot.id);
}
diff --git a/packages/tax-engine/src/optimizer.ts b/packages/tax-engine/src/optimizer.ts
index 0458492e..53a01151 100644
--- a/packages/tax-engine/src/optimizer.ts
+++ b/packages/tax-engine/src/optimizer.ts
@@ -1,7 +1,7 @@
/**
* Method Comparison Engine
*
- * Compares FIFO, LIFO, and HIFO cost basis methods for a hypothetical sale,
+ * Compares all applicable cost basis methods for a hypothetical sale,
* recommending the optimal method based on tax impact, wash sale risk, and
* potential savings.
*
@@ -13,42 +13,49 @@ import type { SimulationInput, SimulationResult } from "./simulator";
import { simulateSale } from "./simulator";
import type { AcquisitionRecord } from "./wash-sale";
-/** Result of comparing all three cost basis methods. */
+/** Reason codes for the recommended method (for i18n on the frontend). */
+export type RecommendedReasonCode =
+ | "identical"
+ | "lowest_gain"
+ | "largest_loss_clean"
+ | "largest_loss";
+
+/** All non-SPECIFIC_ID methods supported by the simulator. */
+const COMPARABLE_METHODS = [
+ "FIFO",
+ "LIFO",
+ "HIFO",
+ "GERMANY_FIFO",
+ "PMPA",
+ "TOTAL_AVERAGE",
+ "UK_SHARE_POOLING",
+] as const;
+
+type ComparableMethod = (typeof COMPARABLE_METHODS)[number];
+
+/** Result of comparing all cost basis methods. */
export interface ComparisonResult {
- /** FIFO simulation result */
- fifo: SimulationResult;
- /** LIFO simulation result */
- lifo: SimulationResult;
- /** HIFO simulation result */
- hifo: SimulationResult;
- /** Recommended method */
- recommended: "FIFO" | "LIFO" | "HIFO";
- /** Human-readable reason for the recommendation */
- recommendedReason: string;
+ /** Simulation results keyed by method name */
+ methods: Record;
+ /** Recommended method name */
+ recommended: ComparableMethod;
+ /** i18n reason code — translate on the frontend */
+ recommendedReasonCode: RecommendedReasonCode;
/** Absolute difference between best and worst projected gain/loss */
savings: number;
}
-type MethodName = "FIFO" | "LIFO" | "HIFO";
-
interface MethodEntry {
- name: MethodName;
+ name: ComparableMethod;
result: SimulationResult;
}
/**
- * Compare all three cost basis methods (FIFO, LIFO, HIFO) for a hypothetical
- * sale and recommend the optimal method.
+ * Compare all applicable cost basis methods for a hypothetical sale and
+ * recommend the optimal method.
*
* Deep-clones lots for each simulation so the caller's data is never mutated.
- * Each method is simulated independently via `simulateSale`.
- *
- * Recommendation logic:
- * - If all results are gains: recommend the method with the smallest gain (lowest tax).
- * - If there are losses: recommend the method with the largest loss (most deduction),
- * but downgrade methods that trigger wash sales when others do not.
- * - If all three methods produce identical results: recommend FIFO as the default.
- * - savings = Math.abs(worst.projectedGainLoss - best.projectedGainLoss)
+ * SPECIFIC_ID is excluded because it requires explicit lot selection.
*
* @param lots - Current tax lots (will NOT be mutated)
* @param input - Simulation parameters (without method)
@@ -60,51 +67,38 @@ export function compareAllMethods(
input: Omit,
acquisitions?: AcquisitionRecord[],
): ComparisonResult {
- const fifo = simulateSale(lots, { ...input, method: "FIFO" }, acquisitions);
- const lifo = simulateSale(lots, { ...input, method: "LIFO" }, acquisitions);
- const hifo = simulateSale(lots, { ...input, method: "HIFO" }, acquisitions);
+ const entries: MethodEntry[] = COMPARABLE_METHODS.map((m) => ({
+ name: m,
+ result: simulateSale(lots, { ...input, method: m }, acquisitions),
+ }));
- const entries: MethodEntry[] = [
- { name: "FIFO", result: fifo },
- { name: "LIFO", result: lifo },
- { name: "HIFO", result: hifo },
- ];
-
- const { recommended, recommendedReason } = pickRecommendation(entries);
+ const { recommended, recommendedReasonCode } = pickRecommendation(entries);
const allGainLoss = entries.map((e) => e.result.projectedGainLoss);
const worst = Math.max(...allGainLoss);
const best = Math.min(...allGainLoss);
const savings = Math.abs(worst - best);
+ const methods = Object.fromEntries(
+ entries.map((e) => [e.name, e.result]),
+ ) as Record;
+
return {
- fifo,
- lifo,
- hifo,
+ methods,
recommended,
- recommendedReason,
+ recommendedReasonCode,
savings,
};
}
-/**
- * Pick the recommended method from the three simulation results.
- *
- * @param entries - The three method entries to compare
- * @returns The recommended method name and reason
- */
function pickRecommendation(entries: MethodEntry[]): {
- recommended: MethodName;
- recommendedReason: string;
+ recommended: ComparableMethod;
+ recommendedReasonCode: RecommendedReasonCode;
} {
- // Check if all three produce identical gain/loss
const gains = entries.map((e) => e.result.projectedGainLoss);
- if (gains[0] === gains[1] && gains[1] === gains[2]) {
- return {
- recommended: "FIFO",
- recommendedReason:
- "All methods produce identical results; FIFO recommended as the standard default.",
- };
+ const allIdentical = gains.every((g) => g === gains[0]);
+ if (allIdentical) {
+ return { recommended: "FIFO", recommendedReasonCode: "identical" };
}
const allGains = entries.every((e) => e.result.projectedGainLoss >= 0);
@@ -116,61 +110,43 @@ function pickRecommendation(entries: MethodEntry[]): {
return pickLargestLoss(entries);
}
-/**
- * When all methods produce gains, recommend the one with the smallest gain
- * (i.e., lowest tax liability).
- */
function pickLowestGain(entries: MethodEntry[]): {
- recommended: MethodName;
- recommendedReason: string;
+ recommended: ComparableMethod;
+ recommendedReasonCode: RecommendedReasonCode;
} {
- // Sort ascending by projectedGainLoss — smallest first
const sorted = [...entries].sort(
(a, b) => a.result.projectedGainLoss - b.result.projectedGainLoss,
);
-
return {
recommended: sorted[0].name,
- recommendedReason: `${sorted[0].name} produces the smallest taxable gain, minimizing tax liability.`,
+ recommendedReasonCode: "lowest_gain",
};
}
-/**
- * When at least one method produces a loss, recommend the one with the
- * largest loss (most deduction). Methods that trigger wash sales while
- * others do not are downgraded.
- */
function pickLargestLoss(entries: MethodEntry[]): {
- recommended: MethodName;
- recommendedReason: string;
+ recommended: ComparableMethod;
+ recommendedReasonCode: RecommendedReasonCode;
} {
- // Check wash sale status across methods
const someHaveWash = entries.some((e) => e.result.washSaleRisk);
const someClean = entries.some((e) => !e.result.washSaleRisk);
const shouldDowngradeWash = someHaveWash && someClean;
- // Filter candidates: exclude wash-sale methods if others are clean
let candidates = shouldDowngradeWash
? entries.filter((e) => !e.result.washSaleRisk)
: entries;
- // If all were filtered out (shouldn't happen), fall back to all entries
if (candidates.length === 0) {
candidates = entries;
}
- // Sort ascending by projectedGainLoss — most negative (largest loss) first
const sorted = [...candidates].sort(
(a, b) => a.result.projectedGainLoss - b.result.projectedGainLoss,
);
- const best = sorted[0];
- const reason = shouldDowngradeWash
- ? `${best.name} provides the largest deductible loss without triggering a wash sale.`
- : `${best.name} provides the largest deductible loss, maximizing tax deductions.`;
-
return {
- recommended: best.name,
- recommendedReason: reason,
+ recommended: sorted[0].name,
+ recommendedReasonCode: shouldDowngradeWash
+ ? "largest_loss_clean"
+ : "largest_loss",
};
}
diff --git a/packages/tax-engine/src/parsers/binance.ts b/packages/tax-engine/src/parsers/binance.ts
index 15d51a5c..3749cf93 100644
--- a/packages/tax-engine/src/parsers/binance.ts
+++ b/packages/tax-engine/src/parsers/binance.ts
@@ -2,8 +2,18 @@
* Binance CSV Format Parsers
*
* Supports two formats:
- * 1. Binance International — Trade History export
- * Columns: Date(UTC), Pair, Side, Price, Executed, Amount, Fee
+ * 1. Binance International — Trade History export (multi-language)
+ * EN: Date(UTC), Pair, Side, Price, Executed, Amount, Fee
+ * ZH: 时间, 交易对, 类型, 价格, 数量, 成交额, 手续费
+ * JA: 日時, ペア, 売買, 価格, 数量, 合計, 手数料
+ * KO: 날짜, 거래쌍, 유형, 가격, 수량, 총액, 수수료
+ * TR: Tarih, İşlem Çifti, Taraf, Fiyat, Miktar, Toplam, Komisyon
+ * ES: Fecha, Par, Lado, Precio, Ejecutado, Monto, Comisión
+ * PT: Data, Par, Lado, Preço, Executado, Valor, Taxa
+ * DE: Datum, Paar, Seite, Preis, Ausgeführt, Betrag, Gebühr
+ * FR: Date, Paire, Côté, Prix, Exécuté, Montant, Frais
+ * RU: Дата, Пара, Сторона, Цена, Исполнено, Сумма, Комиссия
+ * VI: Ngày, Cặp, Phía, Giá, Đã thực hiện, Số tiền, Phí
*
* 2. Binance US — Transaction History export
* Columns: Date, Type, Asset, Amount, Status, Balance, Fee
@@ -16,14 +26,278 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+// ─── Multi-language column name mappings ────────────
+// Each array lists all known translations for a semantic column.
+// csv-core normalizes headers to lowercase + trim, so all entries are lowercase.
+
+const COL_TIMESTAMP = [
+ "date(utc)",
+ "date (utc)",
+ "date",
+ "time",
+ "时间", // ZH (Simplified)
+ "時間", // ZH (Traditional)
+ "日時",
+ "日時(utc)", // JA
+ "날짜",
+ "시간",
+ "일시", // KO
+ "tarih", // TR
+ "fecha", // ES
+ "data", // PT
+ "datum", // DE
+ "дата", // RU
+ "ngày", // VI
+];
+
+const COL_PAIR = [
+ "pair",
+ "market",
+ "trading pair",
+ "symbol",
+ "交易对", // ZH (Simplified)
+ "交易對", // ZH (Traditional)
+ "ペア",
+ "取引ペア",
+ "通貨ペア", // JA
+ "거래쌍",
+ "거래 쌍", // KO
+ "işlem çifti", // TR
+ "par", // ES / PT
+ "paire", // FR
+ "paar", // DE
+ "пара", // RU
+ "cặp", // VI
+];
+
+const COL_SIDE = [
+ "side",
+ "type",
+ "direction",
+ "类型",
+ "方向", // ZH (Simplified)
+ "類型", // ZH (Traditional)
+ "タイプ",
+ "売買",
+ "注文タイプ", // JA
+ "유형",
+ "종류",
+ "매매구분", // KO
+ "taraf",
+ "yön", // TR
+ "lado",
+ "tipo", // ES / PT
+ "côté", // FR
+ "seite", // DE
+ "сторона",
+ "тип", // RU
+ "phía",
+ "loại", // VI
+];
+
+const COL_PRICE = [
+ "price",
+ "avg trading price",
+ "trade price",
+ "价格", // ZH (Simplified)
+ "價格", // ZH (Traditional)
+ "価格",
+ "取引価格", // JA
+ "가격", // KO
+ "fiyat", // TR
+ "precio", // ES
+ "preço", // PT
+ "preis", // DE
+ "prix", // FR
+ "цена", // RU
+ "giá", // VI
+];
+
+const COL_EXECUTED = [
+ "executed",
+ "filled",
+ "quantity",
+ "qty",
+ "数量", // ZH (Simplified)
+ "數量", // ZH (Traditional)
+ "数量",
+ "約定数量", // JA
+ "수량",
+ "체결수량", // KO
+ "miktar",
+ "gerçekleşen", // TR
+ "ejecutado",
+ "cantidad", // ES
+ "executado",
+ "quantidade", // PT
+ "ausgeführt",
+ "menge", // DE
+ "exécuté",
+ "quantité", // FR
+ "исполнено",
+ "количество", // RU
+ "đã thực hiện",
+ "số lượng", // VI
+];
+
+const COL_TOTAL = [
+ "total",
+ "amount",
+ "vol",
+ "turnover",
+ "成交额",
+ "成交额 ", // ZH (Simplified, note trailing space variant)
+ "成交額", // ZH (Traditional)
+ "合計",
+ "約定代金", // JA
+ "총액",
+ "거래대금", // KO
+ "toplam",
+ "tutar", // TR
+ "monto",
+ "total", // ES
+ "montante",
+ "valor", // PT
+ "betrag",
+ "gesamt", // DE
+ "montant", // FR
+ "сумма",
+ "итого", // RU
+ "số tiền",
+ "tổng", // VI
+];
+
+const COL_FEE = [
+ "fee",
+ "commission",
+ "trading fee",
+ "手续费", // ZH (Simplified)
+ "手續費", // ZH (Traditional)
+ "手数料", // JA
+ "수수료", // KO
+ "komisyon",
+ "ücret", // TR
+ "comisión",
+ "tarifa", // ES
+ "taxa",
+ "comissão", // PT
+ "gebühr",
+ "provision", // DE
+ "frais", // FR
+ "комиссия", // RU
+ "phí", // VI
+];
+
+const COL_FEE_ASSET = [
+ "fee coin",
+ "fee asset",
+ "fee currency",
+ "手续费结算币种", // ZH (Simplified)
+ "手續費結算幣種", // ZH (Traditional)
+ "手数料通貨",
+ "手数料コイン", // JA
+ "수수료 통화",
+ "수수료 코인", // KO
+ "komisyon coin",
+ "ücret coin", // TR
+ "moneda comisión", // ES
+ "moeda taxa", // PT
+ "gebühr coin", // DE
+ "devise frais", // FR
+ "валюта комиссии", // RU
+ "đồng phí", // VI
+];
+
+const COL_BASE_ASSET = [
+ "base asset",
+ "base coin",
+ "base currency",
+ "基准货币", // ZH (Simplified)
+ "基準貨幣", // ZH (Traditional)
+ "基軸通貨",
+ "基準通貨", // JA
+ "기준통화",
+ "기준 통화", // KO
+ "temel varlık", // TR
+ "activo base",
+ "moneda base", // ES
+ "ativo base",
+ "moeda base", // PT
+ "basiswährung", // DE
+ "actif de base", // FR
+ "базовый актив",
+ "базовая валюта", // RU
+];
+
+const COL_QUOTE_ASSET = [
+ "quote asset",
+ "quote coin",
+ "quote currency",
+ "计价货币", // ZH (Simplified)
+ "計價貨幣", // ZH (Traditional)
+ "決済通貨",
+ "建値通貨", // JA
+ "견적통화",
+ "견적 통화",
+ "호가통화", // KO
+ "karşı varlık", // TR
+ "activo cotizado",
+ "moneda cotizada", // ES
+ "ativo cotado",
+ "moeda cotada", // PT
+ "kurswährung", // DE
+ "actif de cotation", // FR
+ "котируемый актив",
+ "котируемая валюта", // RU
+];
+
// ─── Binance International ──────────────────────────
function mapBinanceSide(side: string): ParsedTransaction["type"] {
const upper = side.toUpperCase().trim();
if (upper === "BUY") return "BUY";
if (upper === "SELL") return "SELL";
+ // Multi-language buy/sell keywords
+ const buyKeywords = [
+ "买入",
+ "買入",
+ "購入", // ZH / JA
+ "매수", // KO
+ "aliş",
+ "al", // TR
+ "compra",
+ "comprar", // ES / PT
+ "achat",
+ "acheter", // FR
+ "kauf",
+ "kaufen", // DE
+ "покупка",
+ "купить", // RU
+ "mua", // VI
+ ];
+ const sellKeywords = [
+ "卖出",
+ "賣出",
+ "売却", // ZH / JA
+ "매도", // KO
+ "satış",
+ "sat", // TR
+ "venta",
+ "vender", // ES / PT
+ "vente",
+ "vendre", // FR
+ "verkauf",
+ "verkaufen", // DE
+ "продажа",
+ "продать", // RU
+ "bán", // VI
+ ];
+ const lower = side.toLowerCase().trim();
+ if (buyKeywords.includes(lower)) return "BUY";
+ if (sellKeywords.includes(lower)) return "SELL";
return "TRADE";
}
@@ -52,18 +326,90 @@ function parsePair(pair: string): { base: string; quote: string } | null {
/**
* Detect Binance International trade history CSV.
+ * Supports headers in EN, ZH, JA, KO, TR, ES, PT, DE, FR, RU, VI.
*/
export function isBinanceCsv(csv: string): boolean {
- const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
- return (
- (firstLine.includes("date(utc)") || firstLine.includes("date (utc)")) &&
- firstLine.includes("pair") &&
- firstLine.includes("side")
- );
+ const firstLine = csv.split("\n")[0] || "";
+ const lower = normalizeKey(firstLine.toLowerCase());
+
+ // Strategy: English Binance uses the distinctive "date(utc)" header that no
+ // other exchange uses. For non-English, we check language-specific column
+ // name combinations that are unique to Binance exports.
+
+ // 1) English: require "date(utc)" (distinctive) + "pair" + "side"
+ const hasDateUtc =
+ lower.includes("date(utc)") || lower.includes("date (utc)");
+ if (hasDateUtc && lower.includes("pair") && lower.includes("side")) {
+ return true;
+ }
+
+ // 2) Non-English: check for language-specific header combinations.
+ // Each combo uses at least 2 distinctive non-English column names.
+ const LANG_COMBOS: string[][] = [
+ // ZH-Simplified: 时间 + 交易对 + 类型 (not 方向, which is OKX)
+ ["时间", "交易对", "类型"],
+ // ZH-Simplified (alt): 时间 + 交易对 + 基准货币 (10-col format)
+ ["时间", "交易对", "基准货币"],
+ // ZH-Traditional: 時間 + 交易對 + 類型
+ ["時間", "交易對", "類型"],
+ // ZH-Traditional (alt): 時間 + 交易對 + 基準貨幣
+ ["時間", "交易對", "基準貨幣"],
+ // JA: 日時 + ペア or 売買
+ ["日時", "ペア"],
+ ["日時", "売買"],
+ ["日時", "取引ペア"],
+ // KO: 날짜 + 거래쌍
+ ["날짜", "거래쌍"],
+ ["일시", "거래쌍"],
+ // TR: tarih + işlem çifti
+ ["tarih", "işlem çifti"],
+ // ES: fecha + par + lado (need all 3 to avoid false positives)
+ ["fecha", "lado"],
+ // PT: data + par + lado
+ ["data", "lado"],
+ // FR: paire + côté
+ ["paire", "côté"],
+ // DE: datum + paar
+ ["datum", "paar"],
+ // RU: дата + пара
+ ["дата", "пара"],
+ // VI: ngày + cặp
+ ["ngày", "cặp"],
+ ];
+
+ for (const combo of LANG_COMBOS) {
+ if (combo.every((term) => lower.includes(normalizeKey(term)))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Resolve base/quote from explicit columns or by parsing the pair string.
+ * Supports multi-language base/quote asset column names.
+ */
+function resolvePair(
+ row: Record,
+): { base: string; quote: string } | null {
+ const baseCol = resolveCol(row, COL_BASE_ASSET);
+ const quoteCol = resolveCol(row, COL_QUOTE_ASSET);
+ if (baseCol && quoteCol) {
+ return {
+ base: baseCol.toUpperCase().trim(),
+ quote: quoteCol.toUpperCase().trim(),
+ };
+ }
+ // Fallback: parse pair string
+ const pairStr = resolveCol(row, COL_PAIR);
+ return parsePair(pairStr.replace(/\//g, ""));
}
/**
* Parse Binance International trade history CSV.
+ * Supports column headers in 11 languages:
+ * EN, ZH, ZH-Hant, JA, KO, TR, ES, PT, DE, FR, RU, VI.
*/
export function parseBinanceCsv(csv: string): CsvParseResult {
const objects = parseCsvToObjects(csv);
@@ -75,35 +421,29 @@ export function parseBinanceCsv(csv: string): CsvParseResult {
const rowNum = i + 2;
try {
- // Find timestamp — try common column name variants
- const tsRaw = row["date(utc)"] || row["date (utc)"] || row["date"] || "";
+ const tsRaw = resolveCol(row, COL_TIMESTAMP);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
continue;
}
- const pairStr = row["pair"] || row["market"] || "";
- const pair = parsePair(pairStr);
+ const pair = resolvePair(row);
if (!pair) {
errors.push({
row: rowNum,
- message: `Cannot parse pair: "${pairStr}"`,
+ message: `Cannot parse pair from row`,
});
continue;
}
- const side = row["side"] || row["type"] || "";
+ const side = resolveCol(row, COL_SIDE);
const type = mapBinanceSide(side);
- const executed = safeParseNumber(
- row["executed"] || row["filled"] || row["amount"],
- );
- const price = safeParseNumber(row["price"] || row["avg trading price"]);
- const total = safeParseNumber(
- row["amount"] || row["total"] || row["vol"],
- );
- const fee = safeParseNumber(row["fee"]);
+ const executed = safeParseNumber(resolveCol(row, COL_EXECUTED));
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
const tx: ParsedTransaction = {
type,
@@ -128,9 +468,8 @@ export function parseBinanceCsv(csv: string): CsvParseResult {
if (fee && fee > 0) {
tx.feeAmount = fee;
- // Binance fee column sometimes contains the asset name
- const feeAssetRaw = row["fee coin"] || row["fee asset"] || "";
- tx.feeAsset = feeAssetRaw.toUpperCase() || pair.quote;
+ const feeAssetRaw = resolveCol(row, COL_FEE_ASSET);
+ tx.feeAsset = feeAssetRaw.toUpperCase().trim() || pair.quote;
}
transactions.push(tx);
diff --git a/packages/tax-engine/src/parsers/bitget.ts b/packages/tax-engine/src/parsers/bitget.ts
index 44bc70f5..e9eec1b6 100644
--- a/packages/tax-engine/src/parsers/bitget.ts
+++ b/packages/tax-engine/src/parsers/bitget.ts
@@ -16,8 +16,97 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+/* ── Column name candidates (lowercase — csv-core lowercases headers) ── */
+
+const COL_TIME = [
+ "order time",
+ "trade time",
+ "ctime",
+ "time",
+ "timestamp",
+ "date",
+ "下单时间", // ZH Simplified
+ "下單時間", // ZH Traditional
+ "注文時間", // JA
+ "주문 시간", // KO
+];
+
+const COL_SYMBOL = [
+ "trading pair",
+ "symbol",
+ "pair",
+ "交易对", // ZH Simplified
+ "交易對", // ZH Traditional
+ "銘柄", // JA
+ "거래쌍", // KO
+];
+
+const COL_SIDE = [
+ "side",
+ "direction",
+ "方向", // ZH
+ "売買", // JA
+ "유형", // KO
+];
+
+const COL_PRICE = [
+ "filled price",
+ "priceavg",
+ "price avg",
+ "price",
+ "avg. filled price",
+ "成交价", // ZH Simplified
+ "成交價", // ZH Traditional
+ "約定価格", // JA
+ "체결 가격", // KO
+];
+
+const COL_QTY = [
+ "filled amount",
+ "size",
+ "basevolume",
+ "base volume",
+ "qty",
+ "amount",
+ "成交量", // ZH Simplified
+ "成交數量", // ZH Traditional
+ "約定数量", // JA
+ "체결 수량", // KO
+];
+
+const COL_TOTAL = [
+ "total",
+ "quotevolume",
+ "quote volume",
+ "value",
+ "funds",
+ "总额", // ZH Simplified
+ "總額", // ZH Traditional
+ "合計", // JA
+ "총액", // KO
+];
+
+const COL_FEE = [
+ "fee",
+ "手续费", // ZH Simplified
+ "手續費", // ZH Traditional
+ "手数料", // JA
+ "수수료", // KO
+];
+
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "feecurrency",
+ "fee ccy",
+ "手续费币种", // ZH Simplified
+ "手續費幣種", // ZH Traditional
+ "手数料通貨", // JA
+ "수수료 통화", // KO
+];
+
const FIAT_CURRENCIES = new Set([
"USD",
"USDT",
@@ -49,19 +138,27 @@ const KNOWN_QUOTES = [
*/
export function isBitgetCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const norm = normalizeKey(firstLine);
// Bitget-specific: "trading pair" or ("priceavg"/"basevolume") plus "side"
if (
- firstLine.includes("trading pair") &&
- firstLine.includes("side") &&
- (firstLine.includes("filled") || firstLine.includes("total"))
+ norm.includes("trading pair") &&
+ norm.includes("side") &&
+ (norm.includes("filled") || norm.includes("total"))
)
return true;
- if (firstLine.includes("priceavg") && firstLine.includes("basevolume"))
+ if (norm.includes("priceavg") && norm.includes("basevolume")) return true;
+ if (
+ norm.includes("symbol") &&
+ norm.includes("side") &&
+ norm.includes("quotevolume")
+ )
return true;
+ // Chinese: "交易对"/"交易對" + "方向" + "成交量" + "下单时间"/"下單時間"
if (
- firstLine.includes("symbol") &&
- firstLine.includes("side") &&
- firstLine.includes("quotevolume")
+ (norm.includes("交易对") || norm.includes("交易對")) &&
+ norm.includes("方向") &&
+ (norm.includes("成交量") || norm.includes("成交數量")) &&
+ (norm.includes("下单时间") || norm.includes("下單時間"))
)
return true;
return false;
@@ -135,14 +232,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp — multiple possible column names
- const tsRaw =
- row["order time"] ||
- row["trade time"] ||
- row["ctime"] ||
- row["time"] ||
- row["timestamp"] ||
- row["date"] ||
- "";
+ const tsRaw = resolveCol(row, COL_TIME);
// cTime might be Unix milliseconds
let timestamp: string | null = null;
@@ -161,12 +251,7 @@ function parseTradeRow(
}
// Parse symbol
- const symbolRaw = (
- row["trading pair"] ||
- row["symbol"] ||
- row["pair"] ||
- ""
- ).trim();
+ const symbolRaw = resolveCol(row, COL_SYMBOL).trim();
const parsed = splitSymbol(symbolRaw);
if (!parsed) {
errors.push({ row: rowNum, message: `Invalid symbol: "${symbolRaw}"` });
@@ -174,45 +259,26 @@ function parseTradeRow(
}
const [base, quote] = parsed;
- const side = (row["side"] || row["direction"] || "").toLowerCase().trim();
- const price = safeParseNumber(
- row["filled price"] ||
- row["priceavg"] ||
- row["price avg"] ||
- row["price"] ||
- row["avg. filled price"],
- );
- const qty = safeParseNumber(
- row["filled amount"] ||
- row["size"] ||
- row["basevolume"] ||
- row["base volume"] ||
- row["qty"] ||
- row["amount"],
- );
- const total = safeParseNumber(
- row["total"] ||
- row["quotevolume"] ||
- row["quote volume"] ||
- row["value"] ||
- row["funds"],
- );
- const fee = safeParseNumber(row["fee"]);
- const feeCurrency = (
- row["fee currency"] ||
- row["feecurrency"] ||
- row["fee ccy"] ||
- ""
- )
- .toUpperCase()
- .trim();
+ const side = resolveCol(row, COL_SIDE).toLowerCase().trim();
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const qty = safeParseNumber(resolveCol(row, COL_QTY));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
+ const feeCurrency = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
if (!qty || qty <= 0) {
errors.push({ row: rowNum, message: "Invalid quantity" });
return null;
}
- const isBuy = side === "buy";
+ // Multi-language buy/sell mapping
+ const isBuy =
+ side === "buy" ||
+ side === "买入" ||
+ side === "買入" ||
+ side === "買い" ||
+ side === "매수";
+
const isFiatQuote = FIAT_CURRENCIES.has(quote);
const computedTotal = total || (price ? price * qty : 0);
diff --git a/packages/tax-engine/src/parsers/bybit.ts b/packages/tax-engine/src/parsers/bybit.ts
index 8974613f..dacff7be 100644
--- a/packages/tax-engine/src/parsers/bybit.ts
+++ b/packages/tax-engine/src/parsers/bybit.ts
@@ -16,8 +16,101 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+/* ── Column name candidates (lowercase — csv-core lowercases headers) ── */
+
+const COL_TIME = [
+ "order time",
+ "trade time",
+ "exectime",
+ "exec time",
+ "time",
+ "timestamp",
+ "注文時間", // JA
+ "下单时间", // ZH Simplified
+ "下單時間", // ZH Traditional
+ "주문 시간", // KO
+];
+
+const COL_SYMBOL = [
+ "symbol",
+ "trading pair",
+ "pair",
+ "銘柄", // JA
+ "交易对", // ZH Simplified
+ "交易對", // ZH Traditional
+ "거래쌍", // KO
+];
+
+const COL_SIDE = [
+ "side",
+ "direction",
+ "売買", // JA
+ "方向", // ZH
+ "유형", // KO
+];
+
+const COL_PRICE = [
+ "avg. filled price",
+ "filled price",
+ "execprice",
+ "exec price",
+ "price",
+ "平均約定価格", // JA
+ "平均约定价格",
+ "平均成交价", // ZH Simplified
+ "平均成交價", // ZH Traditional
+ "평균 체결 가격", // KO
+];
+
+const COL_QTY = [
+ "filled qty",
+ "execqty",
+ "exec qty",
+ "qty",
+ "amount",
+ "quantity",
+ "約定数量", // JA
+ "成交数量", // ZH Simplified
+ "成交數量", // ZH Traditional
+ "체결 수량", // KO
+];
+
+const COL_TOTAL = [
+ "total",
+ "execvalue",
+ "exec value",
+ "filled total",
+ "funds",
+ "合計", // JA
+ "总额", // ZH Simplified
+ "總額", // ZH Traditional
+ "총액", // KO
+];
+
+const COL_FEE = [
+ "fee",
+ "execfee",
+ "exec fee",
+ "trading fee",
+ "手数料", // JA
+ "手续费", // ZH Simplified
+ "手續費", // ZH Traditional
+ "수수료", // KO
+];
+
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "feecurrency",
+ "fee ccy",
+ "手数料通貨", // JA
+ "手续费币种", // ZH Simplified
+ "手續費幣種", // ZH Traditional
+ "수수료 통화", // KO
+];
+
const FIAT_CURRENCIES = new Set([
"USD",
"USDT",
@@ -49,16 +142,36 @@ const KNOWN_QUOTES = [
*/
export function isBybitCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const norm = normalizeKey(firstLine);
// Bybit-specific: "filled qty" or "execqty" plus "symbol" and ("side" or "direction")
- return (
- firstLine.includes("symbol") &&
- (firstLine.includes("side") || firstLine.includes("direction")) &&
- (firstLine.includes("filled qty") ||
- firstLine.includes("execqty") ||
- firstLine.includes("filled price") ||
- firstLine.includes("execprice") ||
- firstLine.includes("order no"))
- );
+ if (
+ norm.includes("symbol") &&
+ (norm.includes("side") || norm.includes("direction")) &&
+ (norm.includes("filled qty") ||
+ norm.includes("execqty") ||
+ norm.includes("filled price") ||
+ norm.includes("execprice") ||
+ norm.includes("order no"))
+ ) {
+ return true;
+ }
+ // Japanese: "銘柄" + "売買" + "約定数量"
+ if (
+ norm.includes("銘柄") &&
+ norm.includes("売買") &&
+ norm.includes("約定数量")
+ ) {
+ return true;
+ }
+ // Chinese: "交易对"/"交易對" + "方向" + "成交数量"/"成交數量"
+ if (
+ (norm.includes("交易对") || norm.includes("交易對")) &&
+ norm.includes("方向") &&
+ (norm.includes("成交数量") || norm.includes("成交數量"))
+ ) {
+ return true;
+ }
+ return false;
}
/**
@@ -123,14 +236,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp — multiple possible column names
- const tsRaw =
- row["order time"] ||
- row["trade time"] ||
- row["exectime"] ||
- row["exec time"] ||
- row["time"] ||
- row["timestamp"] ||
- "";
+ const tsRaw = resolveCol(row, COL_TIME);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
@@ -138,12 +244,7 @@ function parseTradeRow(
}
// Parse symbol
- const symbolRaw = (
- row["symbol"] ||
- row["trading pair"] ||
- row["pair"] ||
- ""
- ).trim();
+ const symbolRaw = resolveCol(row, COL_SYMBOL).trim();
const parsed = splitSymbol(symbolRaw);
if (!parsed) {
errors.push({ row: rowNum, message: `Invalid symbol: "${symbolRaw}"` });
@@ -151,47 +252,26 @@ function parseTradeRow(
}
const [base, quote] = parsed;
- const side = (row["side"] || row["direction"] || "").toLowerCase().trim();
- const price = safeParseNumber(
- row["avg. filled price"] ||
- row["filled price"] ||
- row["execprice"] ||
- row["exec price"] ||
- row["price"],
- );
- const qty = safeParseNumber(
- row["filled qty"] ||
- row["execqty"] ||
- row["exec qty"] ||
- row["qty"] ||
- row["amount"] ||
- row["quantity"],
- );
- const total = safeParseNumber(
- row["total"] ||
- row["execvalue"] ||
- row["exec value"] ||
- row["filled total"] ||
- row["funds"],
- );
- const fee = safeParseNumber(
- row["fee"] || row["execfee"] || row["exec fee"] || row["trading fee"],
- );
- const feeCurrency = (
- row["fee currency"] ||
- row["feecurrency"] ||
- row["fee ccy"] ||
- ""
- )
- .toUpperCase()
- .trim();
+ const side = resolveCol(row, COL_SIDE).toLowerCase().trim();
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const qty = safeParseNumber(resolveCol(row, COL_QTY));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
+ const feeCurrency = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
if (!qty || qty <= 0) {
errors.push({ row: rowNum, message: "Invalid quantity" });
return null;
}
- const isBuy = side === "buy";
+ // Multi-language buy/sell mapping
+ const isBuy =
+ side === "buy" ||
+ side === "買い" ||
+ side === "买入" ||
+ side === "買入" ||
+ side === "매수";
+
const isFiatQuote = FIAT_CURRENCIES.has(quote);
const computedTotal = total || (price ? price * qty : 0);
diff --git a/packages/tax-engine/src/parsers/col-resolver.ts b/packages/tax-engine/src/parsers/col-resolver.ts
new file mode 100644
index 00000000..b25215df
--- /dev/null
+++ b/packages/tax-engine/src/parsers/col-resolver.ts
@@ -0,0 +1,36 @@
+/**
+ * Shared column name resolver for multi-language CSV parsers.
+ * @license AGPL-3.0
+ */
+
+/**
+ * Normalize a string for comparison: NFC normalize + strip combining marks.
+ * Handles Turkish İ→i̇ (i + combining dot) and similar issues.
+ */
+export function normalizeKey(s: string): string {
+ return s.normalize("NFC").replace(/\u0307/g, "");
+}
+
+/**
+ * Find the first matching column value from a row given a list of candidate names.
+ * Headers are already lowercased + trimmed by csv-core.
+ * Uses Unicode normalization to handle Turkish İ and similar cases.
+ */
+export function resolveCol(
+ row: Record,
+ candidates: string[],
+): string {
+ // Fast path: direct key lookup
+ for (const key of candidates) {
+ const val = row[key];
+ if (val !== undefined && val !== "") return val;
+ }
+ // Slow path: normalized comparison (handles Turkish İ → i̇ etc.)
+ const normalizedCandidates = candidates.map(normalizeKey);
+ for (const [rowKey, rowVal] of Object.entries(row)) {
+ if (!rowVal) continue;
+ const nk = normalizeKey(rowKey);
+ if (normalizedCandidates.includes(nk)) return rowVal;
+ }
+ return "";
+}
diff --git a/packages/tax-engine/src/parsers/crypto-com.ts b/packages/tax-engine/src/parsers/crypto-com.ts
index 755843d9..237fadcb 100644
--- a/packages/tax-engine/src/parsers/crypto-com.ts
+++ b/packages/tax-engine/src/parsers/crypto-com.ts
@@ -9,6 +9,8 @@
* Date, Sent Amount, Sent Currency, Received Amount, Received Currency,
* Fee Amount, Fee Currency, Net Worth Amount, Net Worth Currency, Label, Description, TxHash
*
+ * Supports multi-language headers (English, Chinese Simplified/Traditional, Japanese, Korean).
+ *
* @license AGPL-3.0
*/
@@ -17,8 +19,160 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+// ─── Multi-language column name mappings for Crypto.com ─────────
+
+// App format columns
+const COL_TIMESTAMP = [
+ "timestamp (utc)",
+ "timestamp",
+ "date",
+ "时间戳 (utc)",
+ "时间戳",
+ "時間戳 (utc)", // ZH
+ "タイムスタンプ (utc)",
+ "日時", // JA
+ "타임스탬프 (utc)",
+ "날짜", // KO
+];
+
+const COL_TX_DESCRIPTION = [
+ "transaction description",
+ "交易描述", // ZH
+ "取引説明", // JA
+ "거래 설명", // KO
+];
+
+const COL_TX_KIND = [
+ "transaction kind",
+ "transaction type",
+ "交易类型",
+ "交易類型", // ZH
+ "取引種類", // JA
+ "거래 유형", // KO
+];
+
+const COL_CURRENCY = [
+ "currency",
+ "币种",
+ "幣種", // ZH
+ "通貨", // JA
+ "통화", // KO
+];
+
+const COL_AMOUNT = [
+ "amount",
+ "金额",
+ "金額", // ZH/JA
+ "금액", // KO
+];
+
+const COL_TO_CURRENCY = [
+ "to currency",
+ "目标币种",
+ "目標幣種", // ZH
+ "変換先通貨", // JA
+ "대상 통화", // KO
+];
+
+const COL_TO_AMOUNT = [
+ "to amount",
+ "目标金额",
+ "目標金額", // ZH
+ "変換先金額", // JA
+ "대상 금액", // KO
+];
+
+const COL_NATIVE_AMOUNT_USD = [
+ "native amount (in usd)",
+ "native amount in usd",
+ "本地金额 (usd)",
+ "本地金額 (usd)", // ZH
+ "ネイティブ金額 (usd)", // JA
+];
+
+// Newer format columns
+const COL_SENT_AMOUNT = [
+ "sent amount",
+ "发送金额",
+ "發送金額", // ZH
+ "送金額", // JA
+ "보낸 금액", // KO
+];
+
+const COL_SENT_CURRENCY = [
+ "sent currency",
+ "发送币种",
+ "發送幣種", // ZH
+ "送金通貨", // JA
+ "보낸 통화", // KO
+];
+
+const COL_RECEIVED_AMOUNT = [
+ "received amount",
+ "接收金额",
+ "接收金額", // ZH
+ "受取金額", // JA
+ "받은 금액", // KO
+];
+
+const COL_RECEIVED_CURRENCY = [
+ "received currency",
+ "接收币种",
+ "接收幣種", // ZH
+ "受取通貨", // JA
+ "받은 통화", // KO
+];
+
+const COL_FEE_AMOUNT = [
+ "fee amount",
+ "手续费金额",
+ "手續費金額", // ZH
+ "手数料額", // JA
+ "수수료 금액", // KO
+];
+
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "手续费币种",
+ "手續費幣種", // ZH
+ "手数料通貨", // JA
+ "수수료 통화", // KO
+];
+
+const COL_NET_WORTH_AMOUNT = [
+ "net worth amount",
+ "净值金额",
+ "淨值金額", // ZH
+ "純資産額", // JA
+];
+
+// COL_NET_WORTH_CURRENCY kept for future use by newer format parsers
+// const COL_NET_WORTH_CURRENCY = [
+// "net worth currency",
+// "净值币种", "淨值幣種", // ZH
+// "純資産通貨", // JA
+// ];
+
+const COL_LABEL = [
+ "label",
+ "标签",
+ "標籤", // ZH
+ "ラベル", // JA
+ "라벨", // KO
+];
+
+const COL_DESCRIPTION = [
+ "description",
+ "描述", // ZH
+ "説明", // JA
+ "설명", // KO
+];
+
+// ─── Helpers ────────────────────────────────────────────────────
+
/** Map Crypto.com transaction kind/label to DTax type */
function mapCryptoComType(
kind: string,
@@ -67,13 +221,16 @@ function mapCryptoComType(
*/
export function isCryptoComCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const norm = normalizeKey(firstLine);
// App format (distinctive: "transaction kind" + "native amount")
- if (
- firstLine.includes("transaction kind") &&
- firstLine.includes("native amount")
- ) {
+ if (norm.includes("transaction kind") && norm.includes("native amount"))
return true;
- }
+ // Chinese Simplified: "交易类型" + "本地金额"
+ if (norm.includes("交易类型") && norm.includes("本地金额")) return true;
+ // Chinese Traditional: "交易類型" + "本地金額"
+ if (norm.includes("交易類型") && norm.includes("本地金額")) return true;
+ // Japanese: "取引種類" + "ネイティブ金額"
+ if (norm.includes("取引種類") && norm.includes("ネイティブ金額")) return true;
return false;
}
@@ -95,7 +252,9 @@ export function parseCryptoComCsv(csv: string): CsvParseResult {
// Detect which format variant
const keys = Object.keys(objects[0]);
- const isNewerFormat = keys.some((k) => k.includes("sent amount"));
+ const isNewerFormat = keys.some((k) =>
+ COL_SENT_AMOUNT.some((c) => k.includes(c)),
+ );
for (let i = 0; i < objects.length; i++) {
const row = objects[i];
@@ -138,26 +297,26 @@ function parseNewerFormat(
rowNum: number,
errors: CsvParseError[],
): ParsedTransaction | null {
- const tsRaw = row["date"] || row["timestamp"] || "";
+ const tsRaw = resolveCol(row, COL_TIMESTAMP);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
return null;
}
- const label = row["label"] || "";
- const description = row["description"] || "";
+ const label = resolveCol(row, COL_LABEL);
+ const description = resolveCol(row, COL_DESCRIPTION);
const type = mapCryptoComType(label, description);
const tx: ParsedTransaction = { type, timestamp };
- const sentAmt = safeParseNumber(row["sent amount"]);
- const sentCur = (row["sent currency"] || "").toUpperCase().trim();
- const rcvAmt = safeParseNumber(row["received amount"]);
- const rcvCur = (row["received currency"] || "").toUpperCase().trim();
- const feeAmt = safeParseNumber(row["fee amount"]);
- const feeCur = (row["fee currency"] || "").toUpperCase().trim();
- const netWorth = safeParseNumber(row["net worth amount"]);
+ const sentAmt = safeParseNumber(resolveCol(row, COL_SENT_AMOUNT));
+ const sentCur = resolveCol(row, COL_SENT_CURRENCY).toUpperCase().trim();
+ const rcvAmt = safeParseNumber(resolveCol(row, COL_RECEIVED_AMOUNT));
+ const rcvCur = resolveCol(row, COL_RECEIVED_CURRENCY).toUpperCase().trim();
+ const feeAmt = safeParseNumber(resolveCol(row, COL_FEE_AMOUNT));
+ const feeCur = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
+ const netWorth = safeParseNumber(resolveCol(row, COL_NET_WORTH_AMOUNT));
if (sentAmt && sentCur) {
tx.sentAsset = sentCur;
@@ -202,22 +361,22 @@ function parseAppFormat(
rowNum: number,
errors: CsvParseError[],
): ParsedTransaction | null {
- const tsRaw = row["timestamp (utc)"] || row["timestamp"] || row["date"] || "";
+ const tsRaw = resolveCol(row, COL_TIMESTAMP);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
return null;
}
- const kind = row["transaction kind"] || "";
- const description = row["transaction description"] || "";
+ const kind = resolveCol(row, COL_TX_KIND);
+ const description = resolveCol(row, COL_TX_DESCRIPTION);
const type = mapCryptoComType(kind, description);
- const currency = (row["currency"] || "").toUpperCase().trim();
- const amount = safeParseNumber(row["amount"]);
- const toCurrency = (row["to currency"] || "").toUpperCase().trim();
- const toAmount = safeParseNumber(row["to amount"]);
- const nativeUsd = safeParseNumber(row["native amount (in usd)"]);
+ const currency = resolveCol(row, COL_CURRENCY).toUpperCase().trim();
+ const amount = safeParseNumber(resolveCol(row, COL_AMOUNT));
+ const toCurrency = resolveCol(row, COL_TO_CURRENCY).toUpperCase().trim();
+ const toAmount = safeParseNumber(resolveCol(row, COL_TO_AMOUNT));
+ const nativeUsd = safeParseNumber(resolveCol(row, COL_NATIVE_AMOUNT_USD));
const tx: ParsedTransaction = { type, timestamp };
diff --git a/packages/tax-engine/src/parsers/gate.ts b/packages/tax-engine/src/parsers/gate.ts
index 72469a6f..def90cdc 100644
--- a/packages/tax-engine/src/parsers/gate.ts
+++ b/packages/tax-engine/src/parsers/gate.ts
@@ -16,8 +16,89 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+/* ── Column name candidates (lowercase — csv-core lowercases headers) ── */
+
+const COL_TIME = [
+ "date",
+ "create_time",
+ "time",
+ "timestamp",
+ "日期", // ZH Simplified
+ "日期", // ZH Traditional (same)
+ "日時", // JA
+ "날짜", // KO
+];
+
+const COL_PAIR = [
+ "pair",
+ "currency_pair",
+ "symbol",
+ "交易对", // ZH Simplified
+ "交易對", // ZH Traditional
+ "銘柄", // JA
+ "거래쌍", // KO
+];
+
+const COL_SIDE = [
+ "side",
+ "direction",
+ "方向", // ZH
+ "売買", // JA
+ "유형", // KO
+];
+
+const COL_AMOUNT = [
+ "filled amount",
+ "amount",
+ "qty",
+ "quantity",
+ "成交量", // ZH Simplified
+ "成交數量", // ZH Traditional
+ "約定数量", // JA
+ "체결 수량", // KO
+];
+
+const COL_PRICE = [
+ "filled price",
+ "price",
+ "avg. filled price",
+ "成交价", // ZH Simplified
+ "成交價", // ZH Traditional
+ "約定価格", // JA
+ "체결 가격", // KO
+];
+
+const COL_TOTAL = [
+ "total",
+ "funds",
+ "value",
+ "总额", // ZH Simplified
+ "總額", // ZH Traditional
+ "合計", // JA
+ "총액", // KO
+];
+
+const COL_FEE = [
+ "fee",
+ "手续费", // ZH Simplified
+ "手續費", // ZH Traditional
+ "手数料", // JA
+ "수수료", // KO
+];
+
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "fee_currency",
+ "feecurrency",
+ "手续费币种", // ZH Simplified
+ "手續費幣種", // ZH Traditional
+ "手数料通貨", // JA
+ "수수료 통화", // KO
+];
+
const FIAT_CURRENCIES = new Set([
"USD",
"USDT",
@@ -36,13 +117,20 @@ const FIAT_CURRENCIES = new Set([
*/
export function isGateCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const norm = normalizeKey(firstLine);
// Gate.io: has "currency_pair" or ("pair" + "role"), plus "side" or "fee"
- if (firstLine.includes("currency_pair") && firstLine.includes("side"))
+ if (norm.includes("currency_pair") && norm.includes("side")) return true;
+ if (
+ norm.includes("pair") &&
+ norm.includes("role") &&
+ (norm.includes("filled price") || norm.includes("filled amount"))
+ )
return true;
+ // Chinese: "交易对"/"交易對" + "角色" + "成交价"/"成交價"
if (
- firstLine.includes("pair") &&
- firstLine.includes("role") &&
- (firstLine.includes("filled price") || firstLine.includes("filled amount"))
+ (norm.includes("交易对") || norm.includes("交易對")) &&
+ norm.includes("角色") &&
+ (norm.includes("成交价") || norm.includes("成交價"))
)
return true;
return false;
@@ -92,8 +180,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp
- const tsRaw =
- row["date"] || row["create_time"] || row["time"] || row["timestamp"] || "";
+ const tsRaw = resolveCol(row, COL_TIME);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
@@ -101,9 +188,7 @@ function parseTradeRow(
}
// Parse pair: "BTC_USDT" or "BTC/USDT" or "BTC-USDT"
- const pairRaw = (row["pair"] || row["currency_pair"] || row["symbol"] || "")
- .toUpperCase()
- .trim();
+ const pairRaw = resolveCol(row, COL_PAIR).toUpperCase().trim();
const parts = pairRaw.split(/[_\-\/]/);
if (parts.length !== 2 || !parts[0] || !parts[1]) {
errors.push({ row: rowNum, message: `Invalid pair: "${pairRaw}"` });
@@ -111,30 +196,26 @@ function parseTradeRow(
}
const [base, quote] = parts;
- const side = (row["side"] || row["direction"] || "").toLowerCase().trim();
- const amount = safeParseNumber(
- row["filled amount"] || row["amount"] || row["qty"] || row["quantity"],
- );
- const price = safeParseNumber(
- row["filled price"] || row["price"] || row["avg. filled price"],
- );
- const total = safeParseNumber(row["total"] || row["funds"] || row["value"]);
- const fee = safeParseNumber(row["fee"]);
- const feeCurrency = (
- row["fee currency"] ||
- row["fee_currency"] ||
- row["feecurrency"] ||
- ""
- )
- .toUpperCase()
- .trim();
+ const side = resolveCol(row, COL_SIDE).toLowerCase().trim();
+ const amount = safeParseNumber(resolveCol(row, COL_AMOUNT));
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
+ const feeCurrency = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
if (!amount || amount <= 0) {
errors.push({ row: rowNum, message: "Invalid amount" });
return null;
}
- const isBuy = side === "buy";
+ // Multi-language buy/sell mapping
+ const isBuy =
+ side === "buy" ||
+ side === "买入" ||
+ side === "買入" ||
+ side === "買い" ||
+ side === "매수";
+
const isFiatQuote = FIAT_CURRENCIES.has(quote);
const computedTotal = total || (price ? price * amount : 0);
diff --git a/packages/tax-engine/src/parsers/htx.ts b/packages/tax-engine/src/parsers/htx.ts
index 43ba4363..62aba03e 100644
--- a/packages/tax-engine/src/parsers/htx.ts
+++ b/packages/tax-engine/src/parsers/htx.ts
@@ -17,6 +17,7 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
const FIAT_CURRENCIES = new Set([
@@ -45,11 +46,78 @@ const KNOWN_QUOTES = [
"ETH",
];
+/* ── Column name candidates (EN + JA + ZH) ── */
+const COL_TIME = [
+ "time",
+ "created-at",
+ "created_at",
+ "createdat",
+ "timestamp",
+ "date",
+ "時間",
+ "时间",
+];
+const COL_PAIR = [
+ "pair",
+ "symbol",
+ "trading pair",
+ "通貨ペア",
+ "ペア",
+ "交易对",
+];
+const COL_SIDE = [
+ "side",
+ "direction",
+ "type",
+ "売/買",
+ "売買",
+ "タイプ",
+ "方向",
+ "类型",
+];
+const COL_PRICE = ["price", "avg price", "average price", "価格", "价格"];
+const COL_AMOUNT = [
+ "amount",
+ "filled-amount",
+ "filled amount",
+ "filledamount",
+ "quantity",
+ "qty",
+ "数量",
+];
+const COL_TOTAL = [
+ "total",
+ "turnover",
+ "filled-cash-amount",
+ "filledcashamount",
+ "約定額",
+ "合計",
+ "成交额",
+];
+const COL_FEE = [
+ "fee",
+ "filled-fees",
+ "filledfees",
+ "filled fees",
+ "trading fee",
+ "手数料",
+ "手续费",
+];
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "fee-deduct-currency",
+ "feedeductcurrency",
+ "fee ccy",
+ "手数料通貨",
+ "手续费币种",
+];
+
/**
* Detect if a CSV is in HTX/Huobi trade history format.
*/
export function isHtxCsv(csv: string): boolean {
- const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const rawFirstLine = csv.split("\n")[0] || "";
+ const firstLine = rawFirstLine.toLowerCase();
// HTX standard: "pair" + "side" + "fee currency" + exclude other exchanges
// Exclude: "currency pair" (Gate.io), "pairs" (MEXC), "trading pair" (Bitget),
// "trade id"/"order id" (OKX), "filled price" (Gate.io/Bybit)
@@ -78,6 +146,21 @@ export function isHtxCsv(csv: string): boolean {
if (firstLine.includes("fee-deduct-currency")) {
return true;
}
+ // JA: HTX Japan (BitTrade) — 時間 + 通貨ペア
+ if (rawFirstLine.includes("時間") && rawFirstLine.includes("通貨ペア"))
+ return true;
+ // JA: 時間 + 売/買 (alternate)
+ if (rawFirstLine.includes("時間") && rawFirstLine.includes("売/買"))
+ return true;
+ // ZH: 时间 + 交易对 + 方向 (exclude OKX which has 订单ID/交易ID)
+ if (
+ rawFirstLine.includes("时间") &&
+ rawFirstLine.includes("交易对") &&
+ rawFirstLine.includes("方向") &&
+ !rawFirstLine.includes("订单") &&
+ !rawFirstLine.includes("交易ID")
+ )
+ return true;
return false;
}
@@ -102,15 +185,24 @@ function splitSymbol(symbol: string): [string, string] | null {
/**
* Parse HTX's type field (e.g., "buy-limit", "sell-market") into side.
+ * Also handles Japanese 買/売 and Chinese 买入/卖出.
*/
function parseSide(row: Record): "buy" | "sell" | null {
- const side = (row["side"] || row["direction"] || "").toLowerCase().trim();
- if (side === "buy" || side === "sell") return side;
+ const raw = resolveCol(row, COL_SIDE).trim();
+ const lower = raw.toLowerCase();
+ if (lower === "buy" || lower === "sell") return lower;
// API format: type field like "buy-limit", "sell-market", "buy-market", "sell-limit"
- const typeField = (row["type"] || "").toLowerCase().trim();
- if (typeField.startsWith("buy")) return "buy";
- if (typeField.startsWith("sell")) return "sell";
+ if (lower.startsWith("buy")) return "buy";
+ if (lower.startsWith("sell")) return "sell";
+
+ // JA: 買 = buy, 売 = sell
+ if (raw.includes("買")) return "buy";
+ if (raw.includes("売")) return "sell";
+
+ // ZH: 买 = buy, 卖 = sell
+ if (raw.includes("买")) return "buy";
+ if (raw.includes("卖")) return "sell";
return null;
}
@@ -159,14 +251,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp
- const tsRaw =
- row["time"] ||
- row["created-at"] ||
- row["created_at"] ||
- row["createdat"] ||
- row["timestamp"] ||
- row["date"] ||
- "";
+ const tsRaw = resolveCol(row, COL_TIME);
let timestamp: string | null = null;
const tsNum = Number(tsRaw);
@@ -182,12 +267,7 @@ function parseTradeRow(
}
// Parse symbol/pair
- const symbolRaw = (
- row["pair"] ||
- row["symbol"] ||
- row["trading pair"] ||
- ""
- ).trim();
+ const symbolRaw = resolveCol(row, COL_PAIR).trim();
const parsed = splitSymbol(symbolRaw);
if (!parsed) {
errors.push({ row: rowNum, message: `Invalid symbol: "${symbolRaw}"` });
@@ -203,39 +283,11 @@ function parseTradeRow(
}
const isBuy = side === "buy";
- const price = safeParseNumber(
- row["price"] || row["avg price"] || row["average price"],
- );
- const qty = safeParseNumber(
- row["amount"] ||
- row["filled-amount"] ||
- row["filled amount"] ||
- row["filledamount"] ||
- row["quantity"] ||
- row["qty"],
- );
- const total = safeParseNumber(
- row["total"] ||
- row["turnover"] ||
- row["filled-cash-amount"] ||
- row["filledcashamount"],
- );
- const fee = safeParseNumber(
- row["fee"] ||
- row["filled-fees"] ||
- row["filledfees"] ||
- row["filled fees"] ||
- row["trading fee"],
- );
- const feeCurrency = (
- row["fee currency"] ||
- row["fee-deduct-currency"] ||
- row["feedeductcurrency"] ||
- row["fee ccy"] ||
- ""
- )
- .toUpperCase()
- .trim();
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const qty = safeParseNumber(resolveCol(row, COL_AMOUNT));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
+ const feeCurrency = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
if (!qty || qty <= 0) {
errors.push({ row: rowNum, message: "Invalid quantity" });
diff --git a/packages/tax-engine/src/parsers/mexc.ts b/packages/tax-engine/src/parsers/mexc.ts
index 2293b217..429cbb12 100644
--- a/packages/tax-engine/src/parsers/mexc.ts
+++ b/packages/tax-engine/src/parsers/mexc.ts
@@ -18,8 +18,92 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+/* ── Column name candidates (lowercase — csv-core lowercases headers) ── */
+
+const COL_TIME = [
+ "time",
+ "timestamp",
+ "trade time",
+ "ctime",
+ "时间", // ZH Simplified
+ "時間", // ZH Traditional / JA
+ "거래 시간", // KO
+];
+
+const COL_SYMBOL = [
+ "pairs",
+ "symbol",
+ "pair",
+ "交易对", // ZH Simplified
+ "交易對", // ZH Traditional
+ "銘柄", // JA
+ "거래쌍", // KO
+];
+
+const COL_SIDE = [
+ "side",
+ "direction",
+ "type",
+ "方向", // ZH
+ "売買", // JA
+ "유형", // KO
+];
+
+const COL_PRICE = [
+ "filled price",
+ "price",
+ "average filled price",
+ "成交价", // ZH Simplified
+ "成交價", // ZH Traditional
+ "約定価格", // JA
+ "체결 가격", // KO
+];
+
+const COL_QTY = [
+ "executed amount",
+ "filled quantity",
+ "qty",
+ "amount",
+ "成交量", // ZH Simplified
+ "成交量", // ZH Traditional (same)
+ "約定数量", // JA
+ "체결 수량", // KO
+];
+
+const COL_TOTAL = [
+ "total",
+ "quoteqty",
+ "order amount",
+ "总额", // ZH Simplified
+ "總額", // ZH Traditional
+ "合計", // JA
+ "총액", // KO
+];
+
+const COL_FEE = [
+ "fee",
+ "trading fee",
+ "手续费", // ZH Simplified
+ "手續費", // ZH Traditional
+ "手数料", // JA
+ "수수료", // KO
+];
+
+const COL_COMMISSION = [
+ "commission",
+ "佣金", // ZH
+ "コミッション", // JA
+];
+
+const COL_COMMISSION_ASSET = [
+ "commissionasset",
+ "佣金币种", // ZH
+ "コミッション通貨", // JA
+];
+
const FIAT_CURRENCIES = new Set([
"USD",
"USDT",
@@ -51,21 +135,29 @@ const KNOWN_QUOTES = [
*/
export function isMexcCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
+ const norm = normalizeKey(firstLine);
// MEXC standard: "pairs" + "side" + ("filled price" or "executed amount")
if (
- firstLine.includes("pairs") &&
- firstLine.includes("side") &&
- (firstLine.includes("filled price") ||
- firstLine.includes("executed amount"))
+ norm.includes("pairs") &&
+ norm.includes("side") &&
+ (norm.includes("filled price") || norm.includes("executed amount"))
) {
return true;
}
// MEXC API-style: "symbol" + "commissionasset" (unique to MEXC API)
- if (firstLine.includes("symbol") && firstLine.includes("commissionasset")) {
+ if (norm.includes("symbol") && norm.includes("commissionasset")) {
return true;
}
// MEXC API alt: "symbol" + "isbuyermaker"
- if (firstLine.includes("symbol") && firstLine.includes("isbuyermaker")) {
+ if (norm.includes("symbol") && norm.includes("isbuyermaker")) {
+ return true;
+ }
+ // Chinese: "交易对" + "成交价" + "成交量"
+ if (
+ (norm.includes("交易对") || norm.includes("交易對")) &&
+ (norm.includes("成交价") || norm.includes("成交價")) &&
+ norm.includes("成交量")
+ ) {
return true;
}
return false;
@@ -151,17 +243,21 @@ export function parseMexcCsv(csv: string): CsvParseResult {
};
}
-/** Find a column value, checking for timezone-suffixed variants like "time(utc+08:00)" */
+/**
+ * Find a column value, checking for timezone-suffixed variants like "time(utc+08:00)".
+ * Also checks Chinese/Japanese time column names via resolveCol.
+ */
function findTimeColumn(row: Record): string {
- // Direct match
- if (row["time"]) return row["time"];
+ // First try resolveCol for standard + i18n names
+ const resolved = resolveCol(row, COL_TIME);
+ if (resolved) return resolved;
// Look for time(...) pattern in keys
for (const key of Object.keys(row)) {
- if (key.startsWith("time(") || key === "time") {
+ if (key.startsWith("time(")) {
return row[key];
}
}
- return row["timestamp"] || row["trade time"] || "";
+ return "";
}
/** Parse a single MEXC trade row */
@@ -171,7 +267,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp
- const tsRaw = findTimeColumn(row) || row["ctime"] || "";
+ const tsRaw = findTimeColumn(row);
let timestamp: string | null = null;
// Handle Unix ms timestamp
@@ -188,7 +284,7 @@ function parseTradeRow(
}
// Parse symbol/pair
- const symbolRaw = (row["pairs"] || row["symbol"] || row["pair"] || "").trim();
+ const symbolRaw = resolveCol(row, COL_SYMBOL).trim();
const parsed = splitSymbol(symbolRaw);
if (!parsed) {
errors.push({ row: rowNum, message: `Invalid symbol: "${symbolRaw}"` });
@@ -198,11 +294,15 @@ function parseTradeRow(
// Determine side — standard "side" or API "isbuyermaker"
let isBuy: boolean;
- const sideRaw = (row["side"] || row["direction"] || row["type"] || "")
- .toLowerCase()
- .trim();
+ const sideRaw = resolveCol(row, COL_SIDE).toLowerCase().trim();
if (sideRaw) {
- isBuy = sideRaw === "buy";
+ // Multi-language buy/sell mapping
+ isBuy =
+ sideRaw === "buy" ||
+ sideRaw === "买入" ||
+ sideRaw === "買入" ||
+ sideRaw === "買い" ||
+ sideRaw === "매수";
} else if (row["isbuyermaker"] !== undefined) {
// API format: isBuyerMaker=true means buyer was maker, the taker sold
// But from the user's perspective exporting their own trades, this indicates their side
@@ -213,18 +313,9 @@ function parseTradeRow(
return null;
}
- const price = safeParseNumber(
- row["filled price"] || row["price"] || row["average filled price"],
- );
- const qty = safeParseNumber(
- row["executed amount"] ||
- row["filled quantity"] ||
- row["qty"] ||
- row["amount"],
- );
- const total = safeParseNumber(
- row["total"] || row["quoteqty"] || row["order amount"],
- );
+ const price = safeParseNumber(resolveCol(row, COL_PRICE));
+ const qty = safeParseNumber(resolveCol(row, COL_QTY));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
if (!qty || qty <= 0) {
errors.push({ row: rowNum, message: "Invalid quantity" });
@@ -238,8 +329,8 @@ function parseTradeRow(
let feeAmount: number | undefined;
let feeAsset: string | undefined;
- const commissionRaw = row["commission"];
- const commissionAssetRaw = row["commissionasset"];
+ const commissionRaw = resolveCol(row, COL_COMMISSION);
+ const commissionAssetRaw = resolveCol(row, COL_COMMISSION_ASSET);
if (commissionRaw && commissionAssetRaw) {
// API-style: separate fields
const feeVal = safeParseNumber(commissionRaw);
@@ -249,7 +340,7 @@ function parseTradeRow(
}
} else {
// Standard: concatenated "0.5USDT"
- const feeRaw = row["fee"] || row["trading fee"] || "";
+ const feeRaw = resolveCol(row, COL_FEE);
const parsedFee = parseConcatenatedFee(feeRaw);
if (parsedFee && Math.abs(parsedFee[0]) > 0) {
feeAmount = Math.abs(parsedFee[0]);
diff --git a/packages/tax-engine/src/parsers/okx.ts b/packages/tax-engine/src/parsers/okx.ts
index 84468efc..75e842fd 100644
--- a/packages/tax-engine/src/parsers/okx.ts
+++ b/packages/tax-engine/src/parsers/okx.ts
@@ -16,8 +16,91 @@ import {
safeParseNumber,
safeParseDateToIso,
} from "./csv-core";
+import { normalizeKey, resolveCol } from "./col-resolver";
import type { ParsedTransaction, CsvParseResult, CsvParseError } from "./types";
+/* ── Column name candidates (lowercase — csv-core lowercases headers) ── */
+
+const COL_TIME = [
+ "trade time",
+ "tradetime",
+ "time",
+ "timestamp",
+ "date",
+ "交易时间",
+ "交易時間", // ZH
+ "取引時間",
+ "約定時間", // JA
+ "거래 시간", // KO
+];
+
+const COL_PAIR = [
+ "pair",
+ "instrument",
+ "symbol",
+ "交易对",
+ "交易對",
+ "币对",
+ "幣對", // ZH
+ "ペア",
+ "通貨ペア",
+ "銘柄", // JA
+ "거래쌍", // KO
+];
+
+const COL_SIDE = [
+ "side",
+ "direction",
+ "方向",
+ "类型",
+ "類型", // ZH
+ "売買",
+ "サイド", // JA
+ "유형", // KO
+];
+
+const COL_AMOUNT = [
+ "amount",
+ "quantity",
+ "filled qty",
+ "数量",
+ "數量",
+ "成交量", // ZH
+ "約定数量", // JA
+ "수량", // KO
+];
+
+const COL_TOTAL = [
+ "total",
+ "funds",
+ "filled amount",
+ "总额",
+ "總額",
+ "成交额",
+ "成交額", // ZH
+ "合計",
+ "約定額", // JA
+ "총액", // KO
+];
+
+const COL_FEE = [
+ "fee",
+ "手续费",
+ "手續費", // ZH
+ "手数料", // JA
+ "수수료", // KO
+];
+
+const COL_FEE_CURRENCY = [
+ "fee currency",
+ "feecurrency",
+ "fee ccy",
+ "手续费币种",
+ "手續費幣種", // ZH
+ "手数料通貨", // JA
+ "수수료 통화", // KO
+];
+
const FIAT_CURRENCIES = new Set([
"USD",
"USDT",
@@ -36,12 +119,37 @@ const FIAT_CURRENCIES = new Set([
*/
export function isOkxCsv(csv: string): boolean {
const firstLine = csv.split("\n")[0]?.toLowerCase() || "";
- // OKX exports typically have "pair" or "instrument" and "side"
- return (
- (firstLine.includes("pair") || firstLine.includes("instrument")) &&
- firstLine.includes("side") &&
- (firstLine.includes("fee") || firstLine.includes("total"))
- );
+ const norm = normalizeKey(firstLine);
+ // English: "pair"/"instrument" + "side" + "fee"/"total"
+ if (
+ (norm.includes("pair") || norm.includes("instrument")) &&
+ norm.includes("side") &&
+ (norm.includes("fee") || norm.includes("total"))
+ ) {
+ return true;
+ }
+ // Chinese Simplified: "交易对" + "方向" + "手续费"
+ if (
+ norm.includes("交易对") &&
+ norm.includes("方向") &&
+ norm.includes("手续费")
+ )
+ return true;
+ // Chinese Traditional: "交易對" + "方向" + "手續費"
+ if (
+ norm.includes("交易對") &&
+ norm.includes("方向") &&
+ norm.includes("手續費")
+ )
+ return true;
+ // Japanese: "ペア"/"通貨ペア" + "売買" + "手数料"
+ if (
+ (norm.includes("ペア") || norm.includes("通貨ペア")) &&
+ norm.includes("売買") &&
+ norm.includes("手数料")
+ )
+ return true;
+ return false;
}
/**
@@ -88,12 +196,7 @@ function parseTradeRow(
errors: CsvParseError[],
): ParsedTransaction | null {
// Parse timestamp
- const tsRaw =
- row["trade time"] ||
- row["tradetime"] ||
- row["time"] ||
- row["timestamp"] ||
- "";
+ const tsRaw = resolveCol(row, COL_TIME);
const timestamp = safeParseDateToIso(tsRaw);
if (!timestamp) {
errors.push({ row: rowNum, message: `Invalid date: "${tsRaw}"` });
@@ -101,9 +204,7 @@ function parseTradeRow(
}
// Parse pair: "BTC-USDT" or "BTC/USDT"
- const pair = (row["pair"] || row["instrument"] || row["symbol"] || "")
- .toUpperCase()
- .trim();
+ const pair = resolveCol(row, COL_PAIR).toUpperCase().trim();
const parts = pair.split(/[-\/]/);
if (parts.length !== 2) {
errors.push({ row: rowNum, message: `Invalid pair: "${pair}"` });
@@ -111,29 +212,34 @@ function parseTradeRow(
}
const [base, quote] = parts;
- const side = (row["side"] || row["direction"] || "").toLowerCase().trim();
- const amount = safeParseNumber(
- row["amount"] || row["quantity"] || row["filled qty"],
- );
- const total = safeParseNumber(
- row["total"] || row["funds"] || row["filled amount"],
- );
- const fee = safeParseNumber(row["fee"]);
- const feeCurrency = (
- row["fee currency"] ||
- row["feecurrency"] ||
- row["fee ccy"] ||
- ""
- )
- .toUpperCase()
- .trim();
+ const side = resolveCol(row, COL_SIDE).toLowerCase().trim();
+ const amount = safeParseNumber(resolveCol(row, COL_AMOUNT));
+ const total = safeParseNumber(resolveCol(row, COL_TOTAL));
+ const fee = safeParseNumber(resolveCol(row, COL_FEE));
+ const feeCurrency = resolveCol(row, COL_FEE_CURRENCY).toUpperCase().trim();
if (!amount || amount <= 0) {
errors.push({ row: rowNum, message: "Invalid amount" });
return null;
}
- const isBuy = side === "buy";
+ // Multi-language buy/sell mapping
+ const isBuy =
+ side === "buy" ||
+ side === "买入" ||
+ side === "買入" ||
+ side === "購入" ||
+ side === "매수";
+ const isSell =
+ side === "sell" ||
+ side === "卖出" ||
+ side === "賣出" ||
+ side === "売却" ||
+ side === "매도";
+ if (!isBuy && !isSell) {
+ errors.push({ row: rowNum, message: `Unknown side: "${side}"` });
+ return null;
+ }
const isFiatQuote = FIAT_CURRENCIES.has(quote);
const tx: ParsedTransaction = {
diff --git a/packages/tax-engine/src/parsers/types.ts b/packages/tax-engine/src/parsers/types.ts
index d971c2c1..2f3c644f 100644
--- a/packages/tax-engine/src/parsers/types.ts
+++ b/packages/tax-engine/src/parsers/types.ts
@@ -3,6 +3,8 @@
* @license AGPL-3.0
*/
+import type { TxType } from "@dtax/shared-types";
+
/** Supported exchange CSV formats */
export type CsvFormat =
| "generic"
@@ -32,31 +34,7 @@ export type CsvFormat =
/** A parsed transaction row from CSV */
export interface ParsedTransaction {
/** Transaction type */
- type:
- | "BUY"
- | "SELL"
- | "TRADE"
- | "TRANSFER_IN"
- | "TRANSFER_OUT"
- | "AIRDROP"
- | "STAKING_REWARD"
- | "MINING_REWARD"
- | "INTEREST"
- | "GIFT_RECEIVED"
- | "GIFT_SENT"
- | "DEX_SWAP"
- | "LP_DEPOSIT"
- | "LP_WITHDRAWAL"
- | "LP_REWARD"
- | "WRAP"
- | "UNWRAP"
- | "BRIDGE_OUT"
- | "BRIDGE_IN"
- | "CONTRACT_APPROVAL"
- | "NFT_MINT"
- | "NFT_PURCHASE"
- | "NFT_SALE"
- | "UNKNOWN";
+ type: TxType;
/** ISO timestamp */
timestamp: string;
/** Received asset symbol */
diff --git a/packages/tax-engine/src/price-provider.ts b/packages/tax-engine/src/price-provider.ts
new file mode 100644
index 00000000..ac9f0151
--- /dev/null
+++ b/packages/tax-engine/src/price-provider.ts
@@ -0,0 +1,49 @@
+/**
+ * PriceProvider — abstract interface for historical crypto price lookups.
+ *
+ * Open-source contract: implement this interface to plug in any price source
+ * (CoinGecko, Polygon, Binance, custom oracle, etc.).
+ *
+ * @license AGPL-3.0
+ */
+
+/**
+ * A single historical price data point.
+ * `priceUsd` is the USD fair-market value at the given date.
+ * `source` is a human-readable string for audit trail purposes (IRS FAQ 27).
+ */
+export interface PricePoint {
+ priceUsd: number;
+ source: string; // e.g. "CoinGecko @ 2019-10-21" or "Polygon.io @ 2025-01-15"
+}
+
+/**
+ * Contract for any historical price data provider.
+ *
+ * Implementations should:
+ * - Return null when price data is unavailable (unknown asset, out-of-range date)
+ * - Be idempotent (same inputs → same output)
+ * - Document their rate limits and coverage range
+ */
+export interface PriceProvider {
+ /**
+ * The name of this provider, used in audit trail strings.
+ * e.g. "CoinGecko", "Polygon.io"
+ */
+ readonly name: string;
+
+ /**
+ * Earliest date this provider has reliable data for.
+ * Callers use this to route requests to the appropriate provider.
+ */
+ readonly supportedFrom: Date;
+
+ /**
+ * Fetch the USD price of `asset` on `date`.
+ *
+ * @param asset - Ticker symbol, e.g. "ETH", "BTC"
+ * @param date - The date to look up (time component is ignored; daily granularity)
+ * @returns PricePoint if data is available, null otherwise
+ */
+ getPrice(asset: string, date: Date): Promise;
+}
diff --git a/packages/tax-engine/src/reconciliation/reconciler.ts b/packages/tax-engine/src/reconciliation/reconciler.ts
index 6d506e8e..e54016a2 100644
--- a/packages/tax-engine/src/reconciliation/reconciler.ts
+++ b/packages/tax-engine/src/reconciliation/reconciler.ts
@@ -102,6 +102,34 @@ function generateRebuttal(item: ReconciliationItem): string | undefined {
}
}
+/**
+ * Classify whether a broker entry represents a "covered" or "noncovered" security.
+ * Starting 2026, brokers must report cost basis for "covered" securities:
+ * assets bought on/after Jan 1, 2026 AND kept on the same exchange until sold.
+ */
+function classifyCoverage(
+ brokerEntry: Form1099DAEntry | null,
+): "covered" | "noncovered" | "unknown" {
+ if (!brokerEntry) return "unknown";
+
+ // If broker didn't provide cost basis, it's noncovered
+ if (brokerEntry.costBasis == null || brokerEntry.costBasis === 0) {
+ return "noncovered";
+ }
+
+ // If acquired before 2026-01-01, it's noncovered
+ if (brokerEntry.dateAcquired) {
+ const cutoff = new Date("2026-01-01");
+ if (brokerEntry.dateAcquired < cutoff) {
+ return "noncovered";
+ }
+ return "covered";
+ }
+
+ // No acquisition date = likely transferred in = noncovered
+ return "noncovered";
+}
+
export interface ReconcileOptions {
taxYear: number;
brokerName: string;
@@ -143,6 +171,7 @@ export function reconcile(
proceedsDiff: broker.grossProceeds - dtax.proceeds,
costBasisDiff: (broker.costBasis ?? dtax.costBasis) - dtax.costBasis,
gainLossDiff: (broker.gainLoss ?? dtax.gainLoss) - dtax.gainLoss,
+ coverageStatus: classifyCoverage(broker),
};
item.rebuttalSuggestion = generateRebuttal(item);
items.push(item);
@@ -196,6 +225,7 @@ export function reconcile(
proceedsDiff: broker.grossProceeds - dtax.proceeds,
costBasisDiff: (broker.costBasis ?? dtax.costBasis) - dtax.costBasis,
gainLossDiff: (broker.gainLoss ?? dtax.gainLoss) - dtax.gainLoss,
+ coverageStatus: classifyCoverage(broker),
};
item.rebuttalSuggestion = generateRebuttal(item);
items.push(item);
@@ -227,6 +257,7 @@ export function reconcile(
proceedsDiff: broker.grossProceeds,
costBasisDiff: broker.costBasis ?? 0,
gainLossDiff: broker.gainLoss ?? 0,
+ coverageStatus: classifyCoverage(broker),
};
item.rebuttalSuggestion = generateRebuttal(item);
items.push(item);
@@ -244,6 +275,7 @@ export function reconcile(
proceedsDiff: -dtax.proceeds,
costBasisDiff: -dtax.costBasis,
gainLossDiff: -dtax.gainLoss,
+ coverageStatus: "unknown",
};
item.rebuttalSuggestion = generateRebuttal(item);
items.push(item);
@@ -268,6 +300,9 @@ export function reconcile(
Math.round(items.reduce((s, i) => s + i.proceedsDiff, 0) * 100) / 100,
netGainLossDiff:
Math.round(items.reduce((s, i) => s + i.gainLossDiff, 0) * 100) / 100,
+ coveredCount: items.filter((i) => i.coverageStatus === "covered").length,
+ noncoveredCount: items.filter((i) => i.coverageStatus === "noncovered")
+ .length,
};
return {
diff --git a/packages/tax-engine/src/reconciliation/types.ts b/packages/tax-engine/src/reconciliation/types.ts
index 06392760..96598345 100644
--- a/packages/tax-engine/src/reconciliation/types.ts
+++ b/packages/tax-engine/src/reconciliation/types.ts
@@ -74,6 +74,8 @@ export interface ReconciliationItem {
costBasisDiff: number;
/** Difference in gain/loss */
gainLossDiff: number;
+ /** Whether the broker considers this a "covered" security (basis reported to IRS) */
+ coverageStatus: "covered" | "noncovered" | "unknown";
/** Suggested action for rebuttal */
rebuttalSuggestion?: string;
}
@@ -96,6 +98,10 @@ export interface ReconciliationReport {
netProceedsDiff: number;
/** Net difference in gain/loss */
netGainLossDiff: number;
+ /** Count of covered securities (basis reported to IRS) */
+ coveredCount: number;
+ /** Count of noncovered securities (user self-reports basis) */
+ noncoveredCount: number;
};
items: ReconciliationItem[];
}
diff --git a/packages/tax-engine/src/reports/form8949-pdf.ts b/packages/tax-engine/src/reports/form8949-pdf.ts
index 24137e03..93af224f 100644
--- a/packages/tax-engine/src/reports/form8949-pdf.ts
+++ b/packages/tax-engine/src/reports/form8949-pdf.ts
@@ -8,24 +8,11 @@
*/
import PDFDocument from "pdfkit";
-import type {
- Form8949Report,
- Form8949Line,
- Form8949BoxSummary,
-} from "./form8949";
+import type { Form8949Report, Form8949Line } from "./form8949";
import type { ScheduleDReport } from "./schedule-d";
-
-const MARGIN = 50;
-const PAGE_WIDTH = 612; // Letter
-const CONTENT_WIDTH = PAGE_WIDTH - 2 * MARGIN;
-const LINES_PER_PAGE = 14;
-
-function fmt(n: number): string {
- return n.toLocaleString("en-US", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
-}
+import { MARGIN, LINES_PER_PAGE } from "./pdf/pdf-utils";
+import { renderForm8949Page } from "./pdf/render-form8949";
+import { renderScheduleDPage } from "./pdf/render-schedule-d";
/**
* Generate Form 8949 PDF as a Buffer.
@@ -97,355 +84,3 @@ export function generateForm8949Pdf(
doc.end();
});
}
-
-interface PageOptions {
- box: string;
- taxYear: number;
- lines: Form8949Line[];
- summary?: Form8949BoxSummary;
- taxpayerName?: string;
- taxpayerSSN?: string;
- pageNum: number;
- totalPages: number;
-}
-
-function renderForm8949Page(doc: PDFKit.PDFDocument, opts: PageOptions): void {
- let y = MARGIN;
-
- // Header
- doc
- .fontSize(14)
- .font("Helvetica-Bold")
- .text("Form 8949", MARGIN, y, { align: "center", width: CONTENT_WIDTH });
- y += 18;
-
- doc
- .fontSize(10)
- .font("Helvetica")
- .text("Sales and Other Dispositions of Capital Assets", MARGIN, y, {
- align: "center",
- width: CONTENT_WIDTH,
- });
- y += 14;
-
- doc
- .fontSize(8)
- .font("Helvetica")
- .text(
- `Tax Year ${opts.taxYear} | Box ${opts.box} | Page ${opts.pageNum} of ${opts.totalPages}`,
- MARGIN,
- y,
- { align: "center", width: CONTENT_WIDTH },
- );
- y += 16;
-
- // Taxpayer info
- if (opts.taxpayerName || opts.taxpayerSSN) {
- doc.fontSize(9).font("Helvetica");
- if (opts.taxpayerName) doc.text(`Name: ${opts.taxpayerName}`, MARGIN, y);
- if (opts.taxpayerSSN) doc.text(`SSN: ${opts.taxpayerSSN}`, MARGIN + 300, y);
- y += 14;
- }
-
- // Box description
- const boxDesc: Record = {
- A: "Short-term — basis reported to IRS",
- B: "Short-term — basis NOT reported to IRS",
- C: "Short-term — not on Form 1099-B",
- D: "Long-term — basis reported to IRS",
- E: "Long-term — basis NOT reported to IRS",
- F: "Long-term — not on Form 1099-B",
- };
- doc
- .fontSize(9)
- .font("Helvetica-Bold")
- .text(`Box ${opts.box}: ${boxDesc[opts.box] || ""}`, MARGIN, y);
- y += 18;
-
- // Column headers
- const cols = [
- { label: "(a) Description", x: MARGIN, w: 120 },
- { label: "(b) Acquired", x: MARGIN + 122, w: 72 },
- { label: "(c) Sold", x: MARGIN + 196, w: 72 },
- { label: "(d) Proceeds", x: MARGIN + 270, w: 75 },
- { label: "(e) Cost Basis", x: MARGIN + 347, w: 75 },
- { label: "(f) Code", x: MARGIN + 424, w: 32 },
- { label: "(g) Adjust.", x: MARGIN + 458, w: 55 },
- { label: "(h) Gain/Loss", x: MARGIN + 415, w: 97 },
- ];
-
- // Adjust last column to fit
- cols[7] = { label: "(h) Gain/Loss", x: MARGIN + CONTENT_WIDTH - 75, w: 75 };
- cols[6] = { label: "(g) Adj.", x: MARGIN + CONTENT_WIDTH - 75 - 50, w: 48 };
- cols[5] = { label: "(f)", x: MARGIN + CONTENT_WIDTH - 75 - 50 - 28, w: 26 };
-
- doc.fontSize(7).font("Helvetica-Bold");
- const headerY = y;
- for (const col of cols) {
- doc.text(col.label, col.x, headerY, {
- width: col.w,
- align: col.x > MARGIN + 200 ? "right" : "left",
- });
- }
- y = headerY + 12;
-
- // Separator
- doc
- .moveTo(MARGIN, y)
- .lineTo(MARGIN + CONTENT_WIDTH, y)
- .lineWidth(0.5)
- .stroke();
- y += 4;
-
- // Line items
- doc.fontSize(8).font("Helvetica");
- for (const line of opts.lines) {
- doc.text(line.description, cols[0].x, y, { width: cols[0].w });
- doc.text(line.dateAcquired, cols[1].x, y, { width: cols[1].w });
- doc.text(line.dateSold, cols[2].x, y, { width: cols[2].w });
- doc.text(fmt(line.proceeds), cols[3].x, y, {
- width: cols[3].w,
- align: "right",
- });
- doc.text(fmt(line.costBasis), cols[4].x, y, {
- width: cols[4].w,
- align: "right",
- });
- doc.text(line.adjustmentCode || "", cols[5].x, y, {
- width: cols[5].w,
- align: "right",
- });
- doc.text(
- line.adjustmentAmount ? fmt(line.adjustmentAmount) : "",
- cols[6].x,
- y,
- { width: cols[6].w, align: "right" },
- );
- doc.text(fmt(line.gainLoss), cols[7].x, y, {
- width: cols[7].w,
- align: "right",
- });
- y += 14;
- }
-
- // Summary totals on last page of each box
- if (opts.summary) {
- y += 4;
- doc
- .moveTo(MARGIN, y)
- .lineTo(MARGIN + CONTENT_WIDTH, y)
- .lineWidth(0.5)
- .stroke();
- y += 6;
- doc
- .fontSize(8)
- .font("Helvetica-Bold")
- .text(`Totals (${opts.summary.lineCount} items)`, cols[0].x, y, {
- width: cols[0].w + cols[1].w + cols[2].w,
- });
- doc.text(fmt(opts.summary.totalProceeds), cols[3].x, y, {
- width: cols[3].w,
- align: "right",
- });
- doc.text(fmt(opts.summary.totalCostBasis), cols[4].x, y, {
- width: cols[4].w,
- align: "right",
- });
- doc.text(fmt(opts.summary.totalAdjustments), cols[6].x, y, {
- width: cols[6].w,
- align: "right",
- });
- doc.text(fmt(opts.summary.totalGainLoss), cols[7].x, y, {
- width: cols[7].w,
- align: "right",
- });
- }
-
- // Footer
- doc
- .fontSize(7)
- .font("Helvetica")
- .fillColor("#888888")
- .text(
- "Generated by DTax (dtax.dev) — For informational purposes only",
- MARGIN,
- 740,
- { align: "center", width: CONTENT_WIDTH },
- );
- doc.fillColor("#000000");
-}
-
-function renderScheduleDPage(
- doc: PDFKit.PDFDocument,
- scheduleD: ScheduleDReport,
- taxpayerName?: string,
-): void {
- let y = MARGIN;
-
- doc
- .fontSize(14)
- .font("Helvetica-Bold")
- .text("Schedule D (Form 1040)", MARGIN, y, {
- align: "center",
- width: CONTENT_WIDTH,
- });
- y += 18;
-
- doc
- .fontSize(10)
- .font("Helvetica")
- .text("Capital Gains and Losses", MARGIN, y, {
- align: "center",
- width: CONTENT_WIDTH,
- });
- y += 14;
-
- doc
- .fontSize(8)
- .font("Helvetica")
- .text(`Tax Year ${scheduleD.taxYear}`, MARGIN, y, {
- align: "center",
- width: CONTENT_WIDTH,
- });
- y += 10;
-
- if (taxpayerName) {
- doc.fontSize(9).text(`Name: ${taxpayerName}`, MARGIN, y);
- y += 14;
- }
- y += 6;
-
- const renderPart = (
- title: string,
- lines: ScheduleDReport["partI"],
- netLabel: string,
- netValue: number,
- ) => {
- doc.fontSize(11).font("Helvetica-Bold").text(title, MARGIN, y);
- y += 16;
-
- // Header row
- const lineCol = MARGIN;
- const descCol = MARGIN + 40;
- const proceedsCol = MARGIN + 280;
- const basisCol = MARGIN + 355;
- const glCol = MARGIN + CONTENT_WIDTH - 70;
- const colW = 70;
-
- doc.fontSize(8).font("Helvetica-Bold");
- doc.text("Line", lineCol, y, { width: 35 });
- doc.text("Description", descCol, y, { width: 230 });
- doc.text("Proceeds", proceedsCol, y, { width: colW, align: "right" });
- doc.text("Cost Basis", basisCol, y, { width: colW, align: "right" });
- doc.text("Gain/Loss", glCol, y, { width: colW, align: "right" });
- y += 12;
- doc
- .moveTo(MARGIN, y)
- .lineTo(MARGIN + CONTENT_WIDTH, y)
- .lineWidth(0.5)
- .stroke();
- y += 4;
-
- doc.fontSize(8).font("Helvetica");
- for (const line of lines) {
- doc.text(line.lineNumber, lineCol, y, { width: 35 });
- doc.text(line.description, descCol, y, { width: 230 });
- doc.text(line.proceeds ? fmt(line.proceeds) : "—", proceedsCol, y, {
- width: colW,
- align: "right",
- });
- doc.text(line.costBasis ? fmt(line.costBasis) : "—", basisCol, y, {
- width: colW,
- align: "right",
- });
- doc.text(line.gainLoss ? fmt(line.gainLoss) : "—", glCol, y, {
- width: colW,
- align: "right",
- });
- y += 14;
- }
-
- // Net total
- y += 2;
- doc
- .moveTo(MARGIN, y)
- .lineTo(MARGIN + CONTENT_WIDTH, y)
- .lineWidth(0.5)
- .stroke();
- y += 6;
- doc
- .fontSize(9)
- .font("Helvetica-Bold")
- .text(netLabel, descCol, y, { width: 230 });
- doc.text(fmt(netValue), glCol, y, { width: colW, align: "right" });
- y += 20;
- };
-
- renderPart(
- "Part I — Short-Term Capital Gains and Losses",
- scheduleD.partI,
- "Net Short-Term (Line 7)",
- scheduleD.netShortTerm,
- );
- renderPart(
- "Part II — Long-Term Capital Gains and Losses",
- scheduleD.partII,
- "Net Long-Term (Line 15)",
- scheduleD.netLongTerm,
- );
-
- // Combined summary
- doc
- .moveTo(MARGIN, y)
- .lineTo(MARGIN + CONTENT_WIDTH, y)
- .lineWidth(1)
- .stroke();
- y += 8;
-
- doc
- .fontSize(10)
- .font("Helvetica-Bold")
- .text("Line 16: Combined Net Gain/Loss", MARGIN, y);
- doc.text(
- fmt(scheduleD.combinedNetGainLoss),
- MARGIN + CONTENT_WIDTH - 100,
- y,
- { width: 100, align: "right" },
- );
- y += 18;
-
- if (scheduleD.capitalLossDeduction > 0) {
- doc
- .fontSize(9)
- .font("Helvetica")
- .text("Line 21: Capital Loss Deduction (max $3,000)", MARGIN, y);
- doc.text(
- `(${fmt(scheduleD.capitalLossDeduction)})`,
- MARGIN + CONTENT_WIDTH - 100,
- y,
- { width: 100, align: "right" },
- );
- y += 14;
-
- if (scheduleD.carryoverLoss > 0) {
- doc.text("Loss Carryover to Next Year", MARGIN, y);
- doc.text(fmt(scheduleD.carryoverLoss), MARGIN + CONTENT_WIDTH - 100, y, {
- width: 100,
- align: "right",
- });
- }
- }
-
- // Footer
- doc
- .fontSize(7)
- .font("Helvetica")
- .fillColor("#888888")
- .text(
- "Generated by DTax (dtax.dev) — For informational purposes only",
- MARGIN,
- 740,
- { align: "center", width: CONTENT_WIDTH },
- );
- doc.fillColor("#000000");
-}
diff --git a/packages/tax-engine/src/reports/pdf/pdf-utils.ts b/packages/tax-engine/src/reports/pdf/pdf-utils.ts
new file mode 100644
index 00000000..0a49d113
--- /dev/null
+++ b/packages/tax-engine/src/reports/pdf/pdf-utils.ts
@@ -0,0 +1,61 @@
+/**
+ * Shared constants and utilities for PDF report generation.
+ *
+ * @license AGPL-3.0
+ */
+
+/** Left/right/top margin in points. */
+export const MARGIN = 50;
+
+/** US Letter page width in points. */
+export const PAGE_WIDTH = 612;
+
+/** Printable content width (page minus both margins). */
+export const CONTENT_WIDTH = PAGE_WIDTH - 2 * MARGIN;
+
+/** Maximum line items per Form 8949 page. */
+export const LINES_PER_PAGE = 14;
+
+/**
+ * IRS Form 8949 box descriptions keyed by letter (A–F).
+ */
+export const BOX_DESCRIPTIONS: Record = {
+ A: "Short-term — basis reported to IRS",
+ B: "Short-term — basis NOT reported to IRS",
+ C: "Short-term — not on Form 1099-B",
+ D: "Long-term — basis reported to IRS",
+ E: "Long-term — basis NOT reported to IRS",
+ F: "Long-term — not on Form 1099-B",
+};
+
+/**
+ * Format a number as US-locale currency string with 2 decimal places.
+ *
+ * @param n - The number to format
+ * @returns Formatted string (e.g. "1,234.56")
+ */
+export function fmt(n: number): string {
+ return n.toLocaleString("en-US", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+}
+
+/**
+ * Render the standard DTax footer at the bottom of a PDF page.
+ *
+ * @param doc - The PDFKit document instance
+ */
+export function renderFooter(doc: PDFKit.PDFDocument): void {
+ doc
+ .fontSize(7)
+ .font("Helvetica")
+ .fillColor("#888888")
+ .text(
+ "Generated by DTax (getdtax.com) — For informational purposes only",
+ MARGIN,
+ 740,
+ { align: "center", width: CONTENT_WIDTH },
+ );
+ doc.fillColor("#000000");
+}
diff --git a/packages/tax-engine/src/reports/pdf/render-form8949.ts b/packages/tax-engine/src/reports/pdf/render-form8949.ts
new file mode 100644
index 00000000..91886431
--- /dev/null
+++ b/packages/tax-engine/src/reports/pdf/render-form8949.ts
@@ -0,0 +1,178 @@
+/**
+ * Renders a single Form 8949 page within a PDFKit document.
+ *
+ * @license AGPL-3.0
+ */
+
+import type { Form8949Line, Form8949BoxSummary } from "../form8949";
+import {
+ MARGIN,
+ CONTENT_WIDTH,
+ BOX_DESCRIPTIONS,
+ fmt,
+ renderFooter,
+} from "./pdf-utils";
+
+/** Options for rendering one page of Form 8949. */
+export interface PageOptions {
+ box: string;
+ taxYear: number;
+ lines: Form8949Line[];
+ summary?: Form8949BoxSummary;
+ taxpayerName?: string;
+ taxpayerSSN?: string;
+ pageNum: number;
+ totalPages: number;
+}
+
+/**
+ * Render a single Form 8949 page with header, line items, and optional summary.
+ *
+ * @param doc - The PDFKit document instance
+ * @param opts - Page layout and data options
+ */
+export function renderForm8949Page(
+ doc: PDFKit.PDFDocument,
+ opts: PageOptions,
+): void {
+ let y = MARGIN;
+
+ // Header
+ doc
+ .fontSize(14)
+ .font("Helvetica-Bold")
+ .text("Form 8949", MARGIN, y, { align: "center", width: CONTENT_WIDTH });
+ y += 18;
+
+ doc
+ .fontSize(10)
+ .font("Helvetica")
+ .text("Sales and Other Dispositions of Capital Assets", MARGIN, y, {
+ align: "center",
+ width: CONTENT_WIDTH,
+ });
+ y += 14;
+
+ doc
+ .fontSize(8)
+ .font("Helvetica")
+ .text(
+ `Tax Year ${opts.taxYear} | Box ${opts.box} | Page ${opts.pageNum} of ${opts.totalPages}`,
+ MARGIN,
+ y,
+ { align: "center", width: CONTENT_WIDTH },
+ );
+ y += 16;
+
+ // Taxpayer info
+ if (opts.taxpayerName || opts.taxpayerSSN) {
+ doc.fontSize(9).font("Helvetica");
+ if (opts.taxpayerName) doc.text(`Name: ${opts.taxpayerName}`, MARGIN, y);
+ if (opts.taxpayerSSN) doc.text(`SSN: ${opts.taxpayerSSN}`, MARGIN + 300, y);
+ y += 14;
+ }
+
+ // Box description
+ doc
+ .fontSize(9)
+ .font("Helvetica-Bold")
+ .text(`Box ${opts.box}: ${BOX_DESCRIPTIONS[opts.box] || ""}`, MARGIN, y);
+ y += 18;
+
+ // Column headers
+ const cols = [
+ { label: "(a) Description", x: MARGIN, w: 120 },
+ { label: "(b) Acquired", x: MARGIN + 122, w: 72 },
+ { label: "(c) Sold", x: MARGIN + 196, w: 72 },
+ { label: "(d) Proceeds", x: MARGIN + 270, w: 75 },
+ { label: "(e) Cost Basis", x: MARGIN + 347, w: 75 },
+ { label: "(f)", x: MARGIN + CONTENT_WIDTH - 75 - 50 - 28, w: 26 },
+ { label: "(g) Adj.", x: MARGIN + CONTENT_WIDTH - 75 - 50, w: 48 },
+ { label: "(h) Gain/Loss", x: MARGIN + CONTENT_WIDTH - 75, w: 75 },
+ ];
+
+ doc.fontSize(7).font("Helvetica-Bold");
+ const headerY = y;
+ for (const col of cols) {
+ doc.text(col.label, col.x, headerY, {
+ width: col.w,
+ align: col.x > MARGIN + 200 ? "right" : "left",
+ });
+ }
+ y = headerY + 12;
+
+ // Separator
+ doc
+ .moveTo(MARGIN, y)
+ .lineTo(MARGIN + CONTENT_WIDTH, y)
+ .lineWidth(0.5)
+ .stroke();
+ y += 4;
+
+ // Line items
+ doc.fontSize(8).font("Helvetica");
+ for (const line of opts.lines) {
+ doc.text(line.description, cols[0].x, y, { width: cols[0].w });
+ doc.text(line.dateAcquired, cols[1].x, y, { width: cols[1].w });
+ doc.text(line.dateSold, cols[2].x, y, { width: cols[2].w });
+ doc.text(fmt(line.proceeds), cols[3].x, y, {
+ width: cols[3].w,
+ align: "right",
+ });
+ doc.text(fmt(line.costBasis), cols[4].x, y, {
+ width: cols[4].w,
+ align: "right",
+ });
+ doc.text(line.adjustmentCode || "", cols[5].x, y, {
+ width: cols[5].w,
+ align: "right",
+ });
+ doc.text(
+ line.adjustmentAmount ? fmt(line.adjustmentAmount) : "",
+ cols[6].x,
+ y,
+ { width: cols[6].w, align: "right" },
+ );
+ doc.text(fmt(line.gainLoss), cols[7].x, y, {
+ width: cols[7].w,
+ align: "right",
+ });
+ y += 14;
+ }
+
+ // Summary totals on last page of each box
+ if (opts.summary) {
+ y += 4;
+ doc
+ .moveTo(MARGIN, y)
+ .lineTo(MARGIN + CONTENT_WIDTH, y)
+ .lineWidth(0.5)
+ .stroke();
+ y += 6;
+ doc
+ .fontSize(8)
+ .font("Helvetica-Bold")
+ .text(`Totals (${opts.summary.lineCount} items)`, cols[0].x, y, {
+ width: cols[0].w + cols[1].w + cols[2].w,
+ });
+ doc.text(fmt(opts.summary.totalProceeds), cols[3].x, y, {
+ width: cols[3].w,
+ align: "right",
+ });
+ doc.text(fmt(opts.summary.totalCostBasis), cols[4].x, y, {
+ width: cols[4].w,
+ align: "right",
+ });
+ doc.text(fmt(opts.summary.totalAdjustments), cols[6].x, y, {
+ width: cols[6].w,
+ align: "right",
+ });
+ doc.text(fmt(opts.summary.totalGainLoss), cols[7].x, y, {
+ width: cols[7].w,
+ align: "right",
+ });
+ }
+
+ // Footer
+ renderFooter(doc);
+}
diff --git a/packages/tax-engine/src/reports/pdf/render-schedule-d.ts b/packages/tax-engine/src/reports/pdf/render-schedule-d.ts
new file mode 100644
index 00000000..eeb92720
--- /dev/null
+++ b/packages/tax-engine/src/reports/pdf/render-schedule-d.ts
@@ -0,0 +1,181 @@
+/**
+ * Renders the Schedule D (Form 1040) page within a PDFKit document.
+ *
+ * @license AGPL-3.0
+ */
+
+import type { ScheduleDReport } from "../schedule-d";
+import { MARGIN, CONTENT_WIDTH, fmt, renderFooter } from "./pdf-utils";
+
+/**
+ * Render a Schedule D summary page showing short-term and long-term
+ * capital gains/losses with combined totals.
+ *
+ * @param doc - The PDFKit document instance
+ * @param scheduleD - Schedule D report data
+ * @param taxpayerName - Optional taxpayer name for the header
+ */
+export function renderScheduleDPage(
+ doc: PDFKit.PDFDocument,
+ scheduleD: ScheduleDReport,
+ taxpayerName?: string,
+): void {
+ let y = MARGIN;
+
+ doc
+ .fontSize(14)
+ .font("Helvetica-Bold")
+ .text("Schedule D (Form 1040)", MARGIN, y, {
+ align: "center",
+ width: CONTENT_WIDTH,
+ });
+ y += 18;
+
+ doc
+ .fontSize(10)
+ .font("Helvetica")
+ .text("Capital Gains and Losses", MARGIN, y, {
+ align: "center",
+ width: CONTENT_WIDTH,
+ });
+ y += 14;
+
+ doc
+ .fontSize(8)
+ .font("Helvetica")
+ .text(`Tax Year ${scheduleD.taxYear}`, MARGIN, y, {
+ align: "center",
+ width: CONTENT_WIDTH,
+ });
+ y += 10;
+
+ if (taxpayerName) {
+ doc.fontSize(9).text(`Name: ${taxpayerName}`, MARGIN, y);
+ y += 14;
+ }
+ y += 6;
+
+ const renderPart = (
+ title: string,
+ lines: ScheduleDReport["partI"],
+ netLabel: string,
+ netValue: number,
+ ) => {
+ doc.fontSize(11).font("Helvetica-Bold").text(title, MARGIN, y);
+ y += 16;
+
+ // Header row
+ const lineCol = MARGIN;
+ const descCol = MARGIN + 40;
+ const proceedsCol = MARGIN + 280;
+ const basisCol = MARGIN + 355;
+ const glCol = MARGIN + CONTENT_WIDTH - 70;
+ const colW = 70;
+
+ doc.fontSize(8).font("Helvetica-Bold");
+ doc.text("Line", lineCol, y, { width: 35 });
+ doc.text("Description", descCol, y, { width: 230 });
+ doc.text("Proceeds", proceedsCol, y, { width: colW, align: "right" });
+ doc.text("Cost Basis", basisCol, y, { width: colW, align: "right" });
+ doc.text("Gain/Loss", glCol, y, { width: colW, align: "right" });
+ y += 12;
+ doc
+ .moveTo(MARGIN, y)
+ .lineTo(MARGIN + CONTENT_WIDTH, y)
+ .lineWidth(0.5)
+ .stroke();
+ y += 4;
+
+ doc.fontSize(8).font("Helvetica");
+ for (const line of lines) {
+ doc.text(line.lineNumber, lineCol, y, { width: 35 });
+ doc.text(line.description, descCol, y, { width: 230 });
+ doc.text(line.proceeds ? fmt(line.proceeds) : "—", proceedsCol, y, {
+ width: colW,
+ align: "right",
+ });
+ doc.text(line.costBasis ? fmt(line.costBasis) : "—", basisCol, y, {
+ width: colW,
+ align: "right",
+ });
+ doc.text(line.gainLoss ? fmt(line.gainLoss) : "—", glCol, y, {
+ width: colW,
+ align: "right",
+ });
+ y += 14;
+ }
+
+ // Net total
+ y += 2;
+ doc
+ .moveTo(MARGIN, y)
+ .lineTo(MARGIN + CONTENT_WIDTH, y)
+ .lineWidth(0.5)
+ .stroke();
+ y += 6;
+ doc
+ .fontSize(9)
+ .font("Helvetica-Bold")
+ .text(netLabel, descCol, y, { width: 230 });
+ doc.text(fmt(netValue), glCol, y, { width: colW, align: "right" });
+ y += 20;
+ };
+
+ renderPart(
+ "Part I — Short-Term Capital Gains and Losses",
+ scheduleD.partI,
+ "Net Short-Term (Line 7)",
+ scheduleD.netShortTerm,
+ );
+ renderPart(
+ "Part II — Long-Term Capital Gains and Losses",
+ scheduleD.partII,
+ "Net Long-Term (Line 15)",
+ scheduleD.netLongTerm,
+ );
+
+ // Combined summary
+ doc
+ .moveTo(MARGIN, y)
+ .lineTo(MARGIN + CONTENT_WIDTH, y)
+ .lineWidth(1)
+ .stroke();
+ y += 8;
+
+ doc
+ .fontSize(10)
+ .font("Helvetica-Bold")
+ .text("Line 16: Combined Net Gain/Loss", MARGIN, y);
+ doc.text(
+ fmt(scheduleD.combinedNetGainLoss),
+ MARGIN + CONTENT_WIDTH - 100,
+ y,
+ { width: 100, align: "right" },
+ );
+ y += 18;
+
+ if (scheduleD.capitalLossDeduction > 0) {
+ doc
+ .fontSize(9)
+ .font("Helvetica")
+ .text("Line 21: Capital Loss Deduction (max $3,000)", MARGIN, y);
+ doc.text(
+ `(${fmt(scheduleD.capitalLossDeduction)})`,
+ MARGIN + CONTENT_WIDTH - 100,
+ y,
+ { width: 100, align: "right" },
+ );
+ y += 14;
+
+ if (scheduleD.carryoverLoss > 0) {
+ doc.text("Loss Carryover to Next Year", MARGIN, y);
+ doc.text(fmt(scheduleD.carryoverLoss), MARGIN + CONTENT_WIDTH - 100, y, {
+ width: 100,
+ align: "right",
+ });
+ }
+ }
+
+ // Footer
+ renderFooter(doc);
+}
diff --git a/packages/tax-engine/src/risk-scanner.ts b/packages/tax-engine/src/risk-scanner.ts
index d87865f3..8e18125c 100644
--- a/packages/tax-engine/src/risk-scanner.ts
+++ b/packages/tax-engine/src/risk-scanner.ts
@@ -131,12 +131,13 @@ export function scanRisks(
const lossTime = loss.timestamp.getTime();
const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;
+ // IRS wash sale: 30 days BEFORE or AFTER the loss sale
const repurchase = yearTxs.find(
(tx) =>
tx.id !== loss.id &&
tx.receivedAsset === lossAsset &&
- tx.timestamp.getTime() > lossTime &&
- tx.timestamp.getTime() - lossTime <= thirtyDaysMs,
+ Math.abs(tx.timestamp.getTime() - lossTime) <= thirtyDaysMs &&
+ tx.timestamp.getTime() !== lossTime,
);
if (repurchase) {
washRiskIds.push(loss.id);
diff --git a/packages/tax-engine/src/simulator.ts b/packages/tax-engine/src/simulator.ts
index d99500ef..9a6388c1 100644
--- a/packages/tax-engine/src/simulator.ts
+++ b/packages/tax-engine/src/simulator.ts
@@ -9,7 +9,12 @@
*/
import { CostBasisCalculator } from "./calculator";
-import type { TaxLot, TaxableEvent, CalculationResult } from "./types";
+import type {
+ CostBasisMethod,
+ TaxLot,
+ TaxableEvent,
+ CalculationResult,
+} from "./types";
import { detectWashSales } from "./wash-sale";
import type { AcquisitionRecord } from "./wash-sale";
@@ -27,7 +32,7 @@ export interface SimulationInput {
/** Simulation date (default: now) */
date?: Date;
/** Cost basis method (default: FIFO) */
- method?: "FIFO" | "LIFO" | "HIFO";
+ method?: CostBasisMethod;
/** Wallet-silo mode */
strictSilo?: boolean;
/** Source wallet/exchange ID for strictSilo */
diff --git a/packages/tax-engine/src/types.ts b/packages/tax-engine/src/types.ts
index 3affc789..d2b6454f 100644
--- a/packages/tax-engine/src/types.ts
+++ b/packages/tax-engine/src/types.ts
@@ -4,7 +4,27 @@
*/
/** Supported cost basis calculation methods */
-export type CostBasisMethod = "FIFO" | "LIFO" | "HIFO" | "SPECIFIC_ID";
+export type CostBasisMethod =
+ | "FIFO"
+ | "LIFO"
+ | "HIFO"
+ | "SPECIFIC_ID"
+ | (string & {});
+
+/**
+ * Strategy interface for pluggable cost basis calculation methods.
+ * Implement this to add new methods (e.g., weighted average, moving average).
+ */
+export interface CostBasisStrategy {
+ /** Unique method name */
+ readonly name: string;
+ /** Calculate gains/losses for a taxable event */
+ calculate(
+ lots: TaxLot[],
+ event: TaxableEvent,
+ strictSilo?: boolean,
+ ): CalculationResult;
+}
/** Lot selection for Specific ID method */
export interface LotSelection {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6fa6cf47..921a43fe 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,19 +13,19 @@ importers:
version: 0.6.0
'@changesets/cli':
specifier: ^2.30.0
- version: 2.30.0(@types/node@20.19.37)
+ version: 2.30.0(@types/node@25.5.0)
husky:
specifier: ^9.1.7
version: 9.1.7
lint-staged:
- specifier: ^16.3.2
- version: 16.3.2
+ specifier: ^16.4.0
+ version: 16.4.0
prettier:
specifier: ^3.2.0
version: 3.8.1
turbo:
- specifier: ^2.0.0
- version: 2.8.14
+ specifier: ^2.8.20
+ version: 2.8.20
typescript:
specifier: ^5.4.0
version: 5.9.3
@@ -33,17 +33,20 @@ importers:
apps/api:
dependencies:
'@anthropic-ai/sdk':
- specifier: ^0.78.0
- version: 0.78.0(zod@3.25.76)
+ specifier: ^0.80.0
+ version: 0.80.0(zod@4.3.6)
'@dtax/shared-types':
specifier: workspace:*
version: link:../../packages/shared-types
'@dtax/tax-engine':
specifier: workspace:*
version: link:../../packages/tax-engine
+ '@fastify/cookie':
+ specifier: ^11.0.2
+ version: 11.0.2
'@fastify/cors':
- specifier: ^10.0.0
- version: 10.1.0
+ specifier: ^11.2.0
+ version: 11.2.0
'@fastify/jwt':
specifier: ^10.0.0
version: 10.0.0
@@ -61,10 +64,10 @@ importers:
version: 5.2.5
'@prisma/client':
specifier: ^6.0.0
- version: 6.19.2(prisma@6.19.2(typescript@5.9.3))(typescript@5.9.3)
+ version: 6.19.2(prisma@6.19.2(magicast@0.5.2)(typescript@5.9.3))(typescript@5.9.3)
'@sentry/node':
- specifier: ^10.43.0
- version: 10.43.0
+ specifier: ^10.45.0
+ version: 10.45.0
archiver:
specifier: ^7.0.1
version: 7.0.1
@@ -72,20 +75,26 @@ importers:
specifier: ^3.0.3
version: 3.0.3
ccxt:
- specifier: ^4.5.42
- version: 4.5.42
+ specifier: ^4.5.44
+ version: 4.5.44
dotenv:
- specifier: ^16.4.0
- version: 16.6.1
+ specifier: ^17.3.1
+ version: 17.3.1
fastify:
- specifier: ^5.0.0
- version: 5.8.1
+ specifier: ^5.8.2
+ version: 5.8.2
fastify-plugin:
specifier: ^5.1.0
version: 5.1.0
fastify-zod-openapi:
- specifier: ^4.1.2
- version: 4.1.2(@fastify/swagger-ui@5.2.5)(@fastify/swagger@9.7.0)(fastify@5.8.1)(zod-openapi@4.2.4(zod@3.25.76))(zod@3.25.76)
+ specifier: ^5.5.0
+ version: 5.5.0(@fastify/swagger-ui@5.2.5)(@fastify/swagger@9.7.0)(fastify@5.8.2)(zod@4.3.6)
+ geoip-lite:
+ specifier: ^2.0.1
+ version: 2.0.1
+ openai:
+ specifier: ^6.32.0
+ version: 6.32.0(ws@8.19.0)(zod@4.3.6)
otpauth:
specifier: ^9.5.0
version: 9.5.0
@@ -93,17 +102,17 @@ importers:
specifier: ^1.5.4
version: 1.5.4
resend:
- specifier: ^6.9.3
- version: 6.9.3
+ specifier: ^6.9.4
+ version: 6.9.4
stripe:
specifier: ^20.4.1
- version: 20.4.1(@types/node@20.19.37)
+ version: 20.4.1(@types/node@25.5.0)
zod:
- specifier: ^3.23.0
- version: 3.25.76
+ specifier: ^4.3.6
+ version: 4.3.6
zod-openapi:
- specifier: ^4.2.4
- version: 4.2.4(zod@3.25.76)
+ specifier: ^5.4.6
+ version: 5.4.6(zod@4.3.6)
devDependencies:
'@types/archiver':
specifier: ^7.0.0
@@ -111,6 +120,9 @@ importers:
'@types/bcryptjs':
specifier: ^3.0.0
version: 3.0.0
+ '@types/geoip-lite':
+ specifier: ^1.4.4
+ version: 1.4.4
'@types/qrcode':
specifier: ^1.5.6
version: 1.5.6
@@ -120,55 +132,110 @@ importers:
ajv-formats:
specifier: ^3.0.1
version: 3.0.1(ajv@8.18.0)
+ eslint:
+ specifier: ^9
+ version: 9.39.4(jiti@2.6.1)
pino-pretty:
specifier: ^13.1.3
version: 13.1.3
prisma:
specifier: ^6.0.0
- version: 6.19.2(typescript@5.9.3)
+ version: 6.19.2(magicast@0.5.2)(typescript@5.9.3)
tsup:
specifier: ^8.0.0
- version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.19))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
tsx:
specifier: ^4.19.0
version: 4.21.0
typescript:
specifier: ^5.4.0
version: 5.9.3
+ typescript-eslint:
+ specifier: ^8.57.2
+ version: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ vite:
+ specifier: ^6.0.0
+ version: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)
vitest:
- specifier: ^2.1.9
- version: 2.1.9(@types/node@20.19.37)(terser@5.46.0)
+ specifier: ^4.1.0
+ version: 4.1.0(@opentelemetry/api@1.9.0)(@types/node@25.5.0)(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))
+
+ apps/docs-site:
+ dependencies:
+ '@astrojs/starlight':
+ specifier: ^0.33.0
+ version: 0.33.2(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
+ astro:
+ specifier: ^5.0.0
+ version: 5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ sharp:
+ specifier: ^0.33.5
+ version: 0.33.5
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+ zod:
+ specifier: ^3.25.76
+ version: 3.25.76
+ devDependencies:
+ '@astrojs/check':
+ specifier: ^0.9.8
+ version: 0.9.8(prettier@3.8.1)(typescript@5.9.3)
apps/web:
dependencies:
'@sentry/nextjs':
- specifier: ^10.43.0
- version: 10.43.0(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.105.4)
- axios:
- specifier: ^1.13.6
- version: 1.13.6
+ specifier: ^10.45.0
+ version: 10.45.0(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.105.4)
+ gray-matter:
+ specifier: ^4.0.3
+ version: 4.0.3
+ lucide-react:
+ specifier: ^0.577.0
+ version: 0.577.0(react@19.2.4)
next:
- specifier: 16.1.6
- version: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ specifier: 16.2.0
+ version: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
next-intl:
specifier: ^4.8.3
- version: 4.8.3(@swc/helpers@0.5.15)(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
+ version: 4.8.3(@swc/helpers@0.5.19)(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3)
+ next-mdx-remote:
+ specifier: ^6.0.0
+ version: 6.0.0(@types/react@19.2.14)(react@19.2.4)
posthog-js:
- specifier: ^1.360.1
- version: 1.360.1
+ specifier: ^1.362.0
+ version: 1.362.0
react:
- specifier: 19.2.3
- version: 19.2.3
+ specifier: 19.2.4
+ version: 19.2.4
react-dom:
- specifier: 19.2.3
- version: 19.2.3(react@19.2.3)
+ specifier: 19.2.4
+ version: 19.2.4(react@19.2.4)
+ react-markdown:
+ specifier: ^10.1.0
+ version: 10.1.0(@types/react@19.2.14)(react@19.2.4)
+ read-excel-file:
+ specifier: ^7.0.2
+ version: 7.0.2
+ reading-time:
+ specifier: ^1.5.0
+ version: 1.5.0
+ recharts:
+ specifier: ^3.8.0
+ version: 3.8.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1)
+ remark-gfm:
+ specifier: ^4.0.1
+ version: 4.0.1
devDependencies:
+ '@openapitools/openapi-generator-cli':
+ specifier: ^2.30.2
+ version: 2.30.2
'@playwright/test':
specifier: ^1.58.2
version: 1.58.2
'@types/node':
- specifier: ^20
- version: 20.19.37
+ specifier: ^25
+ version: 25.5.0
'@types/react':
specifier: ^19
version: 19.2.14
@@ -179,8 +246,8 @@ importers:
specifier: ^9
version: 9.39.4(jiti@2.6.1)
eslint-config-next:
- specifier: 16.1.6
- version: 16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ specifier: 16.2.0
+ version: 16.2.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
typescript:
specifier: ^5
version: 5.9.3
@@ -194,21 +261,24 @@ importers:
specifier: workspace:*
version: link:../tax-engine
devDependencies:
+ '@types/node':
+ specifier: ^25
+ version: 25.5.0
tsup:
specifier: ^8.0.0
- version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.19))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
typescript:
specifier: ^5.4.0
version: 5.9.3
vitest:
specifier: ^2.1.9
- version: 2.1.9(@types/node@20.19.37)(terser@5.46.0)
+ version: 2.1.9(@types/node@25.5.0)(terser@5.46.1)
packages/shared-types:
devDependencies:
tsup:
specifier: ^8.5.1
- version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.19))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
typescript:
specifier: ^5.9.3
version: 5.9.3
@@ -218,27 +288,36 @@ importers:
'@dtax/shared-types':
specifier: workspace:*
version: link:../shared-types
+ decimal.js:
+ specifier: ^10.6.0
+ version: 10.6.0
pdfkit:
- specifier: ^0.17.2
- version: 0.17.2
+ specifier: ^0.18.0
+ version: 0.18.0
devDependencies:
'@types/pdfkit':
specifier: ^0.17.5
version: 0.17.5
+ eslint:
+ specifier: ^9
+ version: 9.39.4(jiti@2.6.1)
tsup:
specifier: ^8.5.1
- version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ version: 8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.19))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
typescript:
specifier: ^5.9.3
version: 5.9.3
+ typescript-eslint:
+ specifier: ^8.57.2
+ version: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
vitest:
specifier: ^2.1.9
- version: 2.1.9(@types/node@20.19.37)(terser@5.46.0)
+ version: 2.1.9(@types/node@25.5.0)(terser@5.46.1)
packages:
- '@anthropic-ai/sdk@0.78.0':
- resolution: {integrity: sha512-PzQhR715td/m1UaaN5hHXjYB8Gl2lF9UVhrrGrZeysiF6Rb74Wc9GCB8hzLdzmQtBd1qe89F9OptgB9Za1Ib5w==}
+ '@anthropic-ai/sdk@0.80.0':
+ resolution: {integrity: sha512-WeXLn7zNVk3yjeshn+xZHvld6AoFUOR3Sep6pSoHho5YbSi6HwcirqgPA5ccFuW8QTVJAAU7N8uQQC6Wa9TG+g==}
hasBin: true
peerDependencies:
zod: ^3.25.0 || ^4.0.0
@@ -246,6 +325,58 @@ packages:
zod:
optional: true
+ '@astrojs/check@0.9.8':
+ resolution: {integrity: sha512-LDng8446QLS5ToKjRHd3bgUdirvemVVExV7nRyJfW2wV36xuv7vDxwy5NWN9zqeSEDgg0Tv84sP+T3yEq+Zlkw==}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+
+ '@astrojs/compiler@2.13.1':
+ resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==}
+
+ '@astrojs/internal-helpers@0.7.6':
+ resolution: {integrity: sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==}
+
+ '@astrojs/language-server@2.16.6':
+ resolution: {integrity: sha512-N990lu+HSFiG57owR0XBkr02BYMgiLCshLf+4QG4v6jjSWkBeQGnzqi+E1L08xFPPJ7eEeXnxPXGLaVv5pa4Ug==}
+ hasBin: true
+ peerDependencies:
+ prettier: ^3.0.0
+ prettier-plugin-astro: '>=0.11.0'
+ peerDependenciesMeta:
+ prettier:
+ optional: true
+ prettier-plugin-astro:
+ optional: true
+
+ '@astrojs/markdown-remark@6.3.11':
+ resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==}
+
+ '@astrojs/mdx@4.3.14':
+ resolution: {integrity: sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+ peerDependencies:
+ astro: ^5.0.0
+
+ '@astrojs/prism@3.3.0':
+ resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+
+ '@astrojs/sitemap@3.7.1':
+ resolution: {integrity: sha512-IzQqdTeskaMX+QDZCzMuJIp8A8C1vgzMBp/NmHNnadepHYNHcxQdGLQZYfkbd2EbRXUfOS+UDIKx8sKg0oWVdw==}
+
+ '@astrojs/starlight@0.33.2':
+ resolution: {integrity: sha512-UpvPBMtZrP/x17uQmdOxm8lUTtmEJ0csTprQT8fd8HSHDn/pSK69fOsSjl6tk83ROMOARC5/DivExSxxJADNSA==}
+ peerDependencies:
+ astro: ^5.1.5
+
+ '@astrojs/telemetry@3.3.0':
+ resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+
+ '@astrojs/yaml2ts@0.2.3':
+ resolution: {integrity: sha512-PJzRmgQzUxI2uwpdX2lXSHtP4G8ocp24/t+bZyf5Fy0SZLSF9f9KXZoMlFM/XCGue+B0nH/2IZ7FpBYQATBsCg==}
+
'@babel/code-frame@7.29.0':
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
engines: {node: '>=6.9.0'}
@@ -292,12 +423,12 @@ packages:
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.28.6':
- resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ '@babel/helpers@7.29.2':
+ resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==}
engines: {node: '>=6.9.0'}
- '@babel/parser@7.29.0':
- resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==}
+ '@babel/parser@7.29.2':
+ resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -305,6 +436,10 @@ packages:
resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
engines: {node: '>=6.9.0'}
+ '@babel/runtime@7.29.2':
+ resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
+ engines: {node: '>=6.9.0'}
+
'@babel/template@7.28.6':
resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
engines: {node: '>=6.9.0'}
@@ -317,6 +452,13 @@ packages:
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
+ '@borewit/text-codec@0.2.2':
+ resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==}
+
+ '@capsizecss/unpack@4.0.0':
+ resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==}
+ engines: {node: '>=18'}
+
'@changesets/apply-release-plan@7.1.0':
resolution: {integrity: sha512-yq8ML3YS7koKQ/9bk1PqO0HMzApIFNwjlwCnwFEXMzNe8NpzeeYYKCmnhWJGkN8g7E51MnWaSbqRcTcdIxUgnQ==}
@@ -378,14 +520,39 @@ packages:
'@changesets/write@0.4.0':
resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
- '@emnapi/core@1.8.1':
- resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
+ '@ctrl/tinycolor@4.2.0':
+ resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==}
+ engines: {node: '>=14'}
+
+ '@emmetio/abbreviation@2.3.3':
+ resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==}
+
+ '@emmetio/css-abbreviation@2.1.8':
+ resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==}
+
+ '@emmetio/css-parser@0.4.1':
+ resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==}
- '@emnapi/runtime@1.8.1':
- resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
+ '@emmetio/html-matcher@1.3.0':
+ resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==}
- '@emnapi/wasi-threads@1.1.0':
- resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+ '@emmetio/scanner@1.0.4':
+ resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==}
+
+ '@emmetio/stream-reader-utils@0.1.0':
+ resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==}
+
+ '@emmetio/stream-reader@2.2.0':
+ resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==}
+
+ '@emnapi/core@1.9.1':
+ resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==}
+
+ '@emnapi/runtime@1.9.1':
+ resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==}
+
+ '@emnapi/wasi-threads@1.2.0':
+ resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==}
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
@@ -393,6 +560,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/aix-ppc64@0.25.12':
+ resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/aix-ppc64@0.27.3':
resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
engines: {node: '>=18'}
@@ -405,6 +578,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm64@0.25.12':
+ resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm64@0.27.3':
resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
engines: {node: '>=18'}
@@ -417,6 +596,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-arm@0.25.12':
+ resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-arm@0.27.3':
resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
engines: {node: '>=18'}
@@ -429,6 +614,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/android-x64@0.25.12':
+ resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/android-x64@0.27.3':
resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
engines: {node: '>=18'}
@@ -441,6 +632,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-arm64@0.25.12':
+ resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-arm64@0.27.3':
resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
engines: {node: '>=18'}
@@ -453,6 +650,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/darwin-x64@0.25.12':
+ resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.27.3':
resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
engines: {node: '>=18'}
@@ -465,6 +668,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-arm64@0.25.12':
+ resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-arm64@0.27.3':
resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
engines: {node: '>=18'}
@@ -477,6 +686,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.25.12':
+ resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.27.3':
resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
engines: {node: '>=18'}
@@ -489,6 +704,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm64@0.25.12':
+ resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm64@0.27.3':
resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
engines: {node: '>=18'}
@@ -501,6 +722,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-arm@0.25.12':
+ resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-arm@0.27.3':
resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
engines: {node: '>=18'}
@@ -513,6 +740,12 @@ packages:
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-ia32@0.25.12':
+ resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-ia32@0.27.3':
resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
engines: {node: '>=18'}
@@ -525,6 +758,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-loong64@0.25.12':
+ resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-loong64@0.27.3':
resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
engines: {node: '>=18'}
@@ -537,6 +776,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-mips64el@0.25.12':
+ resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.27.3':
resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
engines: {node: '>=18'}
@@ -549,6 +794,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-ppc64@0.25.12':
+ resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.27.3':
resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
engines: {node: '>=18'}
@@ -561,6 +812,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-riscv64@0.25.12':
+ resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.27.3':
resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
engines: {node: '>=18'}
@@ -573,6 +830,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-s390x@0.25.12':
+ resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-s390x@0.27.3':
resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
engines: {node: '>=18'}
@@ -585,12 +848,24 @@ packages:
cpu: [x64]
os: [linux]
+ '@esbuild/linux-x64@0.25.12':
+ resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/linux-x64@0.27.3':
resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
+ '@esbuild/netbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
'@esbuild/netbsd-arm64@0.27.3':
resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
engines: {node: '>=18'}
@@ -603,12 +878,24 @@ packages:
cpu: [x64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.25.12':
+ resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.27.3':
resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
+ '@esbuild/openbsd-arm64@0.25.12':
+ resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
'@esbuild/openbsd-arm64@0.27.3':
resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
engines: {node: '>=18'}
@@ -621,12 +908,24 @@ packages:
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.25.12':
+ resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.27.3':
resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
+ '@esbuild/openharmony-arm64@0.25.12':
+ resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
'@esbuild/openharmony-arm64@0.27.3':
resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
engines: {node: '>=18'}
@@ -639,6 +938,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/sunos-x64@0.25.12':
+ resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/sunos-x64@0.27.3':
resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
engines: {node: '>=18'}
@@ -651,6 +956,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-arm64@0.25.12':
+ resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-arm64@0.27.3':
resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
engines: {node: '>=18'}
@@ -663,6 +974,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-ia32@0.25.12':
+ resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-ia32@0.27.3':
resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
engines: {node: '>=18'}
@@ -675,6 +992,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.25.12':
+ resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@esbuild/win32-x64@0.27.3':
resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
engines: {node: '>=18'}
@@ -719,6 +1042,18 @@ packages:
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@expressive-code/core@0.41.7':
+ resolution: {integrity: sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg==}
+
+ '@expressive-code/plugin-frames@0.41.7':
+ resolution: {integrity: sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA==}
+
+ '@expressive-code/plugin-shiki@0.41.7':
+ resolution: {integrity: sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ==}
+
+ '@expressive-code/plugin-text-markers@0.41.7':
+ resolution: {integrity: sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==}
+
'@fastify/accept-negotiator@2.0.1':
resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==}
@@ -728,8 +1063,11 @@ packages:
'@fastify/busboy@3.2.0':
resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==}
- '@fastify/cors@10.1.0':
- resolution: {integrity: sha512-MZyBCBJtII60CU9Xme/iE4aEy8G7QpzGR8zkdXZkDFt7ElEMachbE61tfhAG/bvSaULlqlf0huMT12T7iqEmdQ==}
+ '@fastify/cookie@11.0.2':
+ resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==}
+
+ '@fastify/cors@11.2.0':
+ resolution: {integrity: sha512-LbLHBuSAdGdSFZYTLVA3+Ch2t+sA6nq3Ejc6XLAKiQ6ViS2qFnvicpj0htsx03FyYeLs04HfRNBsz/a8SvbcUw==}
'@fastify/deepmerge@3.2.1':
resolution: {integrity: sha512-N5Oqvltoa2r9z1tbx4xjky0oRR60v+T47Ic4J1ukoVQcptLOrIdRnCSdTGmOmajZuHVKlTnfcmrjyqsGEW1ztA==}
@@ -752,8 +1090,8 @@ packages:
'@fastify/multipart@9.4.0':
resolution: {integrity: sha512-Z404bzZeLSXTBmp/trCBuoVFX28pM7rhv849Q5TsbTFZHuk1lc4QjQITTPK92DKVpXmNtJXeHSSc7GYvqFpxAQ==}
- '@fastify/otel@0.16.0':
- resolution: {integrity: sha512-2304BdM5Q/kUvQC9qJO1KZq3Zn1WWsw+WWkVmFEaj1UE2hEIiuFqrPeglQOwEtw/ftngisqfQ3v70TWMmwhhHA==}
+ '@fastify/otel@0.17.1':
+ resolution: {integrity: sha512-K4wyxfUZx2ux5o+b6BtTqouYFVILohLZmSbA2tKUueJstNcBnoGPVhllCaOvbQ3ZrXdUxUC/fyrSWSCqHhdOPg==}
peerDependencies:
'@opentelemetry/api': ^1.9.0
@@ -810,33 +1148,65 @@ packages:
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
+ '@img/sharp-darwin-arm64@0.33.5':
+ resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [darwin]
+
'@img/sharp-darwin-arm64@0.34.5':
resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
+ '@img/sharp-darwin-x64@0.33.5':
+ resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [darwin]
+
'@img/sharp-darwin-x64@0.34.5':
resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
+ '@img/sharp-libvips-darwin-arm64@1.0.4':
+ resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==}
+ cpu: [arm64]
+ os: [darwin]
+
'@img/sharp-libvips-darwin-arm64@1.2.4':
resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
os: [darwin]
+ '@img/sharp-libvips-darwin-x64@1.0.4':
+ resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==}
+ cpu: [x64]
+ os: [darwin]
+
'@img/sharp-libvips-darwin-x64@1.2.4':
resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
os: [darwin]
+ '@img/sharp-libvips-linux-arm64@1.0.4':
+ resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
+ cpu: [arm64]
+ os: [linux]
+
'@img/sharp-libvips-linux-arm64@1.2.4':
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
+ '@img/sharp-libvips-linux-arm@1.0.5':
+ resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
+ cpu: [arm]
+ os: [linux]
+
'@img/sharp-libvips-linux-arm@1.2.4':
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
@@ -852,32 +1222,64 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@img/sharp-libvips-linux-s390x@1.0.4':
+ resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
+ cpu: [s390x]
+ os: [linux]
+
'@img/sharp-libvips-linux-s390x@1.2.4':
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
+ '@img/sharp-libvips-linux-x64@1.0.4':
+ resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
+ cpu: [x64]
+ os: [linux]
+
'@img/sharp-libvips-linux-x64@1.2.4':
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
+ '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
+ resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
+ cpu: [arm64]
+ os: [linux]
+
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
+ '@img/sharp-libvips-linuxmusl-x64@1.0.4':
+ resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
+ cpu: [x64]
+ os: [linux]
+
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
+ '@img/sharp-linux-arm64@0.33.5':
+ resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
'@img/sharp-linux-arm64@0.34.5':
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ '@img/sharp-linux-arm@0.33.5':
+ resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm]
+ os: [linux]
+
'@img/sharp-linux-arm@0.34.5':
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -896,30 +1298,59 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@img/sharp-linux-s390x@0.33.5':
+ resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [s390x]
+ os: [linux]
+
'@img/sharp-linux-s390x@0.34.5':
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
+ '@img/sharp-linux-x64@0.33.5':
+ resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
'@img/sharp-linux-x64@0.34.5':
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ '@img/sharp-linuxmusl-arm64@0.33.5':
+ resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
'@img/sharp-linuxmusl-arm64@0.34.5':
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
+ '@img/sharp-linuxmusl-x64@0.33.5':
+ resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
'@img/sharp-linuxmusl-x64@0.34.5':
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
+ '@img/sharp-wasm32@0.33.5':
+ resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [wasm32]
+
'@img/sharp-wasm32@0.34.5':
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -931,18 +1362,34 @@ packages:
cpu: [arm64]
os: [win32]
+ '@img/sharp-win32-ia32@0.33.5':
+ resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ia32]
+ os: [win32]
+
'@img/sharp-win32-ia32@0.34.5':
resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ia32]
os: [win32]
+ '@img/sharp-win32-x64@0.33.5':
+ resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [win32]
+
'@img/sharp-win32-x64@0.34.5':
resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
+ '@inquirer/core@6.0.0':
+ resolution: {integrity: sha512-fKi63Khkisgda3ohnskNf5uZJj+zXOaBvOllHsOkdsXRA/ubQLJQrZchFFi57NKbZzkTunXiBMdvWOv71alonw==}
+ engines: {node: '>=14.18.0'}
+
'@inquirer/external-editor@1.0.3':
resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==}
engines: {node: '>=18'}
@@ -952,6 +1399,14 @@ packages:
'@types/node':
optional: true
+ '@inquirer/select@1.3.3':
+ resolution: {integrity: sha512-RzlRISXWqIKEf83FDC9ZtJ3JvuK1l7aGpretf41BCWYrvla2wU8W8MTRNMiPrPJ+1SIqrRC1nZdZ60hD9hRXLg==}
+ engines: {node: '>=14.18.0'}
+
+ '@inquirer/type@1.5.5':
+ resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==}
+ engines: {node: '>=18'}
+
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -975,6 +1430,10 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@lukeed/csprng@1.1.0':
+ resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
+ engines: {node: '>=8'}
+
'@lukeed/ms@2.0.2':
resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==}
engines: {node: '>=8'}
@@ -985,63 +1444,118 @@ packages:
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+ '@mdx-js/mdx@3.1.1':
+ resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
+
+ '@mdx-js/react@3.1.1':
+ resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
+ peerDependencies:
+ '@types/react': '>=16'
+ react: '>=16'
+
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
- '@next/env@16.1.6':
- resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==}
-
- '@next/eslint-plugin-next@16.1.6':
- resolution: {integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==}
+ '@nestjs/axios@4.0.1':
+ resolution: {integrity: sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==}
+ peerDependencies:
+ '@nestjs/common': ^10.0.0 || ^11.0.0
+ axios: ^1.3.1
+ rxjs: ^7.0.0
- '@next/swc-darwin-arm64@16.1.6':
- resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [darwin]
+ '@nestjs/common@11.1.16':
+ resolution: {integrity: sha512-JSIeW+USuMJkkcNbiOdcPkVCeI3TSnXstIVEPpp3HiaKnPRuSbUUKm9TY9o/XpIcPHWUOQItAtC5BiAwFdVITQ==}
+ peerDependencies:
+ class-transformer: '>=0.4.1'
+ class-validator: '>=0.13.2'
+ reflect-metadata: ^0.1.12 || ^0.2.0
+ rxjs: ^7.1.0
+ peerDependenciesMeta:
+ class-transformer:
+ optional: true
+ class-validator:
+ optional: true
- '@next/swc-darwin-x64@16.1.6':
- resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==}
- engines: {node: '>= 10'}
+ '@nestjs/core@11.1.16':
+ resolution: {integrity: sha512-tXWXyCiqWthelJjrE0KLFjf0O98VEt+WPVx5CrqCf+059kIxJ8y1Vw7Cy7N4fwQafWNrmFL2AfN87DDMbVAY0w==}
+ engines: {node: '>= 20'}
+ peerDependencies:
+ '@nestjs/common': ^11.0.0
+ '@nestjs/microservices': ^11.0.0
+ '@nestjs/platform-express': ^11.0.0
+ '@nestjs/websockets': ^11.0.0
+ reflect-metadata: ^0.1.12 || ^0.2.0
+ rxjs: ^7.1.0
+ peerDependenciesMeta:
+ '@nestjs/microservices':
+ optional: true
+ '@nestjs/platform-express':
+ optional: true
+ '@nestjs/websockets':
+ optional: true
+
+ '@next/env@16.2.0':
+ resolution: {integrity: sha512-OZIbODWWAi0epQRCRjNe1VO45LOFBzgiyqmTLzIqWq6u1wrxKnAyz1HH6tgY/Mc81YzIjRPoYsPAEr4QV4l9TA==}
+
+ '@next/eslint-plugin-next@16.2.0':
+ resolution: {integrity: sha512-3D3pEMcGKfENC9Pzlkr67GOm+205+5hRdYPZvHuNIy5sr9k0ybSU8g+sxOO/R/RLEh/gWZ3UlY+5LmEyZ1xgXQ==}
+
+ '@next/swc-darwin-arm64@16.2.0':
+ resolution: {integrity: sha512-/JZsqKzKt01IFoiLLAzlNqys7qk2F3JkcUhj50zuRhKDQkZNOz9E5N6wAQWprXdsvjRP4lTFj+/+36NSv5AwhQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@next/swc-darwin-x64@16.2.0':
+ resolution: {integrity: sha512-/hV8erWq4SNlVgglUiW5UmQ5Hwy5EW/AbbXlJCn6zkfKxTy/E/U3V8U1Ocm2YCTUoFgQdoMxRyRMOW5jYy4ygg==}
+ engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@16.1.6':
- resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==}
+ '@next/swc-linux-arm64-gnu@16.2.0':
+ resolution: {integrity: sha512-GkjL/Q7MWOwqWR9zoxu1TIHzkOI2l2BHCf7FzeQG87zPgs+6WDh+oC9Sw9ARuuL/FUk6JNCgKRkA6rEQYadUaw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@16.1.6':
- resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
+ '@next/swc-linux-arm64-musl@16.2.0':
+ resolution: {integrity: sha512-1ffhC6KY5qWLg5miMlKJp3dZbXelEfjuXt1qcp5WzSCQy36CV3y+JT7OC1WSFKizGQCDOcQbfkH/IjZP3cdRNA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@16.1.6':
- resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
+ '@next/swc-linux-x64-gnu@16.2.0':
+ resolution: {integrity: sha512-FmbDcZQ8yJRq93EJSL6xaE0KK/Rslraf8fj1uViGxg7K4CKBCRYSubILJPEhjSgZurpcPQq12QNOJQ0DRJl6Hg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@16.1.6':
- resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
+ '@next/swc-linux-x64-musl@16.2.0':
+ resolution: {integrity: sha512-HzjIHVkmGAwRbh/vzvoBWWEbb8BBZPxBvVbDQDvzHSf3D8RP/4vjw7MNLDXFF9Q1WEzeQyEj2zdxBtVAHu5Oyw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@16.1.6':
- resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
+ '@next/swc-win32-arm64-msvc@16.2.0':
+ resolution: {integrity: sha512-UMiFNQf5H7+1ZsZPxEsA064WEuFbRNq/kEXyepbCnSErp4f5iut75dBA8UeerFIG3vDaQNOfCpevnERPp2V+nA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@16.1.6':
- resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==}
+ '@next/swc-win32-x64-msvc@16.2.0':
+ resolution: {integrity: sha512-DRrNJKW+/eimrZgdhVN1uvkN1OI4j6Lpefwr44jKQ0YQzztlmOBUUzHuV5GxOMPK3nmodAYElUVCY8ZXo/IWeA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
+ '@noble/ciphers@1.3.0':
+ resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/hashes@1.8.0':
+ resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
+ engines: {node: ^14.21.3 || >=16}
+
'@noble/hashes@2.0.1':
resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
engines: {node: '>= 20.19.0'}
@@ -1062,6 +1576,21 @@ packages:
resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
engines: {node: '>=12.4.0'}
+ '@nuxt/opencollective@0.4.1':
+ resolution: {integrity: sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==}
+ engines: {node: ^14.18.0 || >=16.10.0, npm: '>=5.10.0'}
+ hasBin: true
+
+ '@nuxtjs/opencollective@0.3.2':
+ resolution: {integrity: sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==}
+ engines: {node: '>=8.0.0', npm: '>=5.0.0'}
+ hasBin: true
+
+ '@openapitools/openapi-generator-cli@2.30.2':
+ resolution: {integrity: sha512-rGgLrY88f7/eTBc2wmehhcqQq7/1wEkNQUhvk1NF0nh/bCGGGRfzN6O4U2VHsREtshUT+IUaRoJwq4UeDrRXZQ==}
+ engines: {node: '>=20.19.0'}
+ hasBin: true
+
'@opentelemetry/api-logs@0.207.0':
resolution: {integrity: sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ==}
engines: {node: '>=8.0.0'}
@@ -1070,8 +1599,12 @@ packages:
resolution: {integrity: sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==}
engines: {node: '>=8.0.0'}
- '@opentelemetry/api-logs@0.211.0':
- resolution: {integrity: sha512-swFdZq8MCdmdR22jTVGQDhwqDzcI4M10nhjXkLr1EsIzXgZBqm4ZlmmcWsg3TSNf+3mzgOiqveXmBLZuDi2Lgg==}
+ '@opentelemetry/api-logs@0.212.0':
+ resolution: {integrity: sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==}
+ engines: {node: '>=8.0.0'}
+
+ '@opentelemetry/api-logs@0.213.0':
+ resolution: {integrity: sha512-zRM5/Qj6G84Ej3F1yt33xBVY/3tnMxtL1fiDIxYbDWYaZ/eudVw3/PBiZ8G7JwUxXxjW8gU4g6LnOyfGKYHYgw==}
engines: {node: '>=8.0.0'}
'@opentelemetry/api@1.9.0':
@@ -1090,12 +1623,6 @@ packages:
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
- '@opentelemetry/core@2.5.0':
- resolution: {integrity: sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==}
- engines: {node: ^18.19.0 || >=20.6.0}
- peerDependencies:
- '@opentelemetry/api': '>=1.0.0 <1.10.0'
-
'@opentelemetry/core@2.6.0':
resolution: {integrity: sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg==}
engines: {node: ^18.19.0 || >=20.6.0}
@@ -1108,134 +1635,134 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-amqplib@0.58.0':
- resolution: {integrity: sha512-fjpQtH18J6GxzUZ+cwNhWUpb71u+DzT7rFkg5pLssDGaEber91Y2WNGdpVpwGivfEluMlNMZumzjEqfg8DeKXQ==}
+ '@opentelemetry/instrumentation-amqplib@0.60.0':
+ resolution: {integrity: sha512-q/B2IvoVXRm1M00MvhnzpMN6rKYOszPXVsALi6u0ss4AYHe+TidZEtLW9N1ZhrobI1dSriHnBqqtAOZVAv07sg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-connect@0.54.0':
- resolution: {integrity: sha512-43RmbhUhqt3uuPnc16cX6NsxEASEtn8z/cYV8Zpt6EP4p2h9s4FNuJ4Q9BbEQ2C0YlCCB/2crO1ruVz/hWt8fA==}
+ '@opentelemetry/instrumentation-connect@0.56.0':
+ resolution: {integrity: sha512-PKp+sSZ7AfzMvGgO3VCyo1inwNu+q7A1k9X88WK4PQ+S6Hp7eFk8pie+sWHDTaARovmqq5V2osav3lQej2B0nw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-dataloader@0.28.0':
- resolution: {integrity: sha512-ExXGBp0sUj8yhm6Znhf9jmuOaGDsYfDES3gswZnKr4MCqoBWQdEFn6EoDdt5u+RdbxQER+t43FoUihEfTSqsjA==}
+ '@opentelemetry/instrumentation-dataloader@0.30.0':
+ resolution: {integrity: sha512-MXHP2Q38cd2OhzEBKAIXUi9uBlPEYzF6BNJbyjUXBQ6kLaf93kRC41vNMIz0Nl5mnuwK7fDvKT+/lpx7BXRwdg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-express@0.59.0':
- resolution: {integrity: sha512-pMKV/qnHiW/Q6pmbKkxt0eIhuNEtvJ7sUAyee192HErlr+a1Jx+FZ3WjfmzhQL1geewyGEiPGkmjjAgNY8TgDA==}
+ '@opentelemetry/instrumentation-express@0.61.0':
+ resolution: {integrity: sha512-Xdmqo9RZuZlL29Flg8QdwrrX7eW1CZ7wFQPKHyXljNymgKhN1MCsYuqQ/7uxavhSKwAl7WxkTzKhnqpUApLMvQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-fs@0.30.0':
- resolution: {integrity: sha512-n3Cf8YhG7reaj5dncGlRIU7iT40bxPOjsBEA5Bc1a1g6e9Qvb+JFJ7SEiMlPbUw4PBmxE3h40ltE8LZ3zVt6OA==}
+ '@opentelemetry/instrumentation-fs@0.32.0':
+ resolution: {integrity: sha512-koR6apx0g0wX6RRiPpjA4AFQUQUbXrK16kq4/SZjVp7u5cffJhNkY4TnITxcGA4acGSPYAfx3NHRIv4Khn1axQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-generic-pool@0.54.0':
- resolution: {integrity: sha512-8dXMBzzmEdXfH/wjuRvcJnUFeWzZHUnExkmFJ2uPfa31wmpyBCMxO59yr8f/OXXgSogNgi/uPo9KW9H7LMIZ+g==}
+ '@opentelemetry/instrumentation-generic-pool@0.56.0':
+ resolution: {integrity: sha512-fg+Jffs6fqrf0uQS0hom7qBFKsbtpBiBl8+Vkc63Gx8xh6pVh+FhagmiO6oM0m3vyb683t1lP7yGYq22SiDnqg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-graphql@0.58.0':
- resolution: {integrity: sha512-+yWVVY7fxOs3j2RixCbvue8vUuJ1inHxN2q1sduqDB0Wnkr4vOzVKRYl/Zy7B31/dcPS72D9lo/kltdOTBM3bQ==}
+ '@opentelemetry/instrumentation-graphql@0.61.0':
+ resolution: {integrity: sha512-pUiVASv6nh2XrerTvlbVHh7vKFzscpgwiQ/xvnZuAIzQ5lRjWVdRPUuXbvZJ/Yq79QsE81TZdJ7z9YsXiss1ew==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-hapi@0.57.0':
- resolution: {integrity: sha512-Os4THbvls8cTQTVA8ApLfZZztuuqGEeqog0XUnyRW7QVF0d/vOVBEcBCk1pazPFmllXGEdNbbat8e2fYIWdFbw==}
+ '@opentelemetry/instrumentation-hapi@0.59.0':
+ resolution: {integrity: sha512-33wa4mEr+9+ztwdgLor1SeBu4Opz4IsmpcLETXAd3VmBrOjez8uQtrsOhPCa5Vhbm5gzDlMYTgFRLQzf8/YHFA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-http@0.211.0':
- resolution: {integrity: sha512-n0IaQ6oVll9PP84SjbOCwDjaJasWRHi6BLsbMLiT6tNj7QbVOkuA5sk/EfZczwI0j5uTKl1awQPivO/ldVtsqA==}
+ '@opentelemetry/instrumentation-http@0.213.0':
+ resolution: {integrity: sha512-B978Xsm5XEPGhm1P07grDoaOFLHapJPkOG9h016cJsyWWxmiLnPu2M/4Nrm7UCkHSiLnkXgC+zVGUAIahy8EEA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-ioredis@0.59.0':
- resolution: {integrity: sha512-875UxzBHWkW+P4Y45SoFM2AR8f8TzBMD8eO7QXGCyFSCUMP5s9vtt/BS8b/r2kqLyaRPK6mLbdnZznK3XzQWvw==}
+ '@opentelemetry/instrumentation-ioredis@0.61.0':
+ resolution: {integrity: sha512-hsHDadUtAFbws1YSDc1XW0svGFKiUbqv2td1Cby+UAiwvojm1NyBo/taifH0t8CuFZ0x/2SDm0iuTwrM5pnVOg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-kafkajs@0.20.0':
- resolution: {integrity: sha512-yJXOuWZROzj7WmYCUiyT27tIfqBrVtl1/TwVbQyWPz7rL0r1Lu7kWjD0PiVeTCIL6CrIZ7M2s8eBxsTAOxbNvw==}
+ '@opentelemetry/instrumentation-kafkajs@0.22.0':
+ resolution: {integrity: sha512-wJU4IBQMUikdJAcTChLFqK5lo+flo7pahqd8DSLv7uMxsdOdAHj6RzKYAm8pPfUS6ItKYutYyuicwKaFwQKsoA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-knex@0.55.0':
- resolution: {integrity: sha512-FtTL5DUx5Ka/8VK6P1VwnlUXPa3nrb7REvm5ddLUIeXXq4tb9pKd+/ThB1xM/IjefkRSN3z8a5t7epYw1JLBJQ==}
+ '@opentelemetry/instrumentation-knex@0.57.0':
+ resolution: {integrity: sha512-vMCSh8kolEm5rRsc+FZeTZymWmIJwc40hjIKnXH4O0Dv/gAkJJIRXCsPX5cPbe0c0j/34+PsENd0HqKruwhVYw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-koa@0.59.0':
- resolution: {integrity: sha512-K9o2skADV20Skdu5tG2bogPKiSpXh4KxfLjz6FuqIVvDJNibwSdu5UvyyBzRVp1rQMV6UmoIk6d3PyPtJbaGSg==}
+ '@opentelemetry/instrumentation-koa@0.61.0':
+ resolution: {integrity: sha512-lvrfWe9ShK/D2X4brmx8ZqqeWPfRl8xekU0FCn7C1dHm5k6+rTOOi36+4fnaHAP8lig9Ux6XQ1D4RNIpPCt1WQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.9.0
- '@opentelemetry/instrumentation-lru-memoizer@0.55.0':
- resolution: {integrity: sha512-FDBfT7yDGcspN0Cxbu/k8A0Pp1Jhv/m7BMTzXGpcb8ENl3tDj/51U65R5lWzUH15GaZA15HQ5A5wtafklxYj7g==}
+ '@opentelemetry/instrumentation-lru-memoizer@0.57.0':
+ resolution: {integrity: sha512-cEqpUocSKJfwDtLYTTJehRLWzkZ2eoePCxfVIgGkGkb83fMB71O+y4MvRHJPbeV2bdoWdOVrl8uO0+EynWhTEA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-mongodb@0.64.0':
- resolution: {integrity: sha512-pFlCJjweTqVp7B220mCvCld1c1eYKZfQt1p3bxSbcReypKLJTwat+wbL2YZoX9jPi5X2O8tTKFEOahO5ehQGsA==}
+ '@opentelemetry/instrumentation-mongodb@0.66.0':
+ resolution: {integrity: sha512-d7m9QnAY+4TCWI4q1QRkfrc6fo/92VwssaB1DzQfXNRvu51b78P+HJlWP7Qg6N6nkwdb9faMZNBCZJfftmszkw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-mongoose@0.57.0':
- resolution: {integrity: sha512-MthiekrU/BAJc5JZoZeJmo0OTX6ycJMiP6sMOSRTkvz5BrPMYDqaJos0OgsLPL/HpcgHP7eo5pduETuLguOqcg==}
+ '@opentelemetry/instrumentation-mongoose@0.59.0':
+ resolution: {integrity: sha512-6/jWU+c1NgznkVLDU/2y0bXV2nJo3o9FWZ9mZ9nN6T/JBNRoMnVXZl2FdBmgH+a5MwaWLs5kmRJTP5oUVGIkPw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-mysql2@0.57.0':
- resolution: {integrity: sha512-nHSrYAwF7+aV1E1V9yOOP9TchOodb6fjn4gFvdrdQXiRE7cMuffyLLbCZlZd4wsspBzVwOXX8mpURdRserAhNA==}
+ '@opentelemetry/instrumentation-mysql2@0.59.0':
+ resolution: {integrity: sha512-n9/xrVCRBfG9egVbffnlU1uhr+HX0vF4GgtAB/Bvm48wpFgRidqD8msBMiym1kRYzmpWvJqTxNT47u1MkgBEdw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-mysql@0.57.0':
- resolution: {integrity: sha512-HFS/+FcZ6Q7piM7Il7CzQ4VHhJvGMJWjx7EgCkP5AnTntSN5rb5Xi3TkYJHBKeR27A0QqPlGaCITi93fUDs++Q==}
+ '@opentelemetry/instrumentation-mysql@0.59.0':
+ resolution: {integrity: sha512-r+V/Fh0sm7Ga8/zk/TI5H5FQRAjwr0RrpfPf8kNIehlsKf12XnvIaZi8ViZkpX0gyPEpLXqzqWD6QHlgObgzZw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-pg@0.63.0':
- resolution: {integrity: sha512-dKm/ODNN3GgIQVlbD6ZPxwRc3kleLf95hrRWXM+l8wYo+vSeXtEpQPT53afEf6VFWDVzJK55VGn8KMLtSve/cg==}
+ '@opentelemetry/instrumentation-pg@0.65.0':
+ resolution: {integrity: sha512-W0zpHEIEuyZ8zvb3njaX9AAbHgPYOsSWVOoWmv1sjVRSF6ZpBqtlxBWbU+6hhq1TFWBeWJOXZ8nZS/PUFpLJYQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-redis@0.59.0':
- resolution: {integrity: sha512-JKv1KDDYA2chJ1PC3pLP+Q9ISMQk6h5ey+99mB57/ARk0vQPGZTTEb4h4/JlcEpy7AYT8HIGv7X6l+br03Neeg==}
+ '@opentelemetry/instrumentation-redis@0.61.0':
+ resolution: {integrity: sha512-JnPexA034/0UJRsvH96B0erQoNOqKJZjE2ZRSw9hiTSC23LzE0nJE/u6D+xqOhgUhRnhhcPHq4MdYtmUdYTF+Q==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-tedious@0.30.0':
- resolution: {integrity: sha512-bZy9Q8jFdycKQ2pAsyuHYUHNmCxCOGdG6eg1Mn75RvQDccq832sU5OWOBnc12EFUELI6icJkhR7+EQKMBam2GA==}
+ '@opentelemetry/instrumentation-tedious@0.32.0':
+ resolution: {integrity: sha512-BQS6gG8RJ1foEqfEZ+wxoqlwfCAzb1ZVG0ad8Gfe4x8T658HJCLGLd4E4NaoQd8EvPfLqOXgzGaE/2U4ytDSWA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation-undici@0.21.0':
- resolution: {integrity: sha512-gok0LPUOTz2FQ1YJMZzaHcOzDFyT64XJ8M9rNkugk923/p6lDGms/cRW1cqgqp6N6qcd6K6YdVHwPEhnx9BWbw==}
+ '@opentelemetry/instrumentation-undici@0.23.0':
+ resolution: {integrity: sha512-LL0VySzKVR2cJSFVZaTYpZl1XTpBGnfzoQPe2W7McS2267ldsaEIqtQY6VXs2KCXN0poFjze5110PIpxHDaDGg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.7.0
@@ -1246,14 +1773,14 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation@0.208.0':
- resolution: {integrity: sha512-Eju0L4qWcQS+oXxi6pgh7zvE2byogAkcsVv0OjHF/97iOz1N/aKE6etSGowYkie+YA1uo6DNwdSxaaNnLvcRlA==}
+ '@opentelemetry/instrumentation@0.212.0':
+ resolution: {integrity: sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
- '@opentelemetry/instrumentation@0.211.0':
- resolution: {integrity: sha512-h0nrZEC/zvI994nhg7EgQ8URIHt0uDTwN90r3qQUdZORS455bbx+YebnGeEuFghUT0HlJSrLF4iHw67f+odY+Q==}
+ '@opentelemetry/instrumentation@0.213.0':
+ resolution: {integrity: sha512-3i9NdkET/KvQomeh7UaR/F4r9P25Rx6ooALlWXPIjypcEOUxksCmVu0zA70NBJWlrMW1rPr/LRidFAflLI+s/w==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
@@ -1320,6 +1847,42 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.1.0
+ '@oslojs/encoding@1.1.0':
+ resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
+
+ '@pagefind/darwin-arm64@1.4.0':
+ resolution: {integrity: sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@pagefind/darwin-x64@1.4.0':
+ resolution: {integrity: sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@pagefind/default-ui@1.4.0':
+ resolution: {integrity: sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==}
+
+ '@pagefind/freebsd-x64@1.4.0':
+ resolution: {integrity: sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@pagefind/linux-arm64@1.4.0':
+ resolution: {integrity: sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@pagefind/linux-x64@1.4.0':
+ resolution: {integrity: sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@pagefind/windows-x64@1.4.0':
+ resolution: {integrity: sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==}
+ cpu: [x64]
+ os: [win32]
+
'@parcel/watcher-android-arm64@2.5.6':
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
engines: {node: '>= 10.0.0'}
@@ -1414,11 +1977,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
- '@posthog/core@1.23.3':
- resolution: {integrity: sha512-nehG2nig9qiU4lEUIyfXQLaBnylm5wdDiIBsp2tBFJX5BcUHNAXSwpkHjKLQ9TDfik0HW1HwZ2mY/3hJgJNToQ==}
+ '@posthog/core@1.24.0':
+ resolution: {integrity: sha512-Wkp9mgNfgdf6+G4C1VMKakm2RXKQFf4bb5/CPQRAjpqv9l6BY36zZrD1+X5Y2XIAzZqbMKRxsDu3V1r6uKu7/A==}
- '@posthog/types@1.360.1':
- resolution: {integrity: sha512-zzvgckmzmjYB7YGnA2cIMtF9thj8O1TMp2YCXcBb+qnGcI5cKTo8j+lO7Kq1Lbwgp7ZPxBWUXfKHg03K5vVdjg==}
+ '@posthog/types@1.362.0':
+ resolution: {integrity: sha512-15wOI5uulkfzpkSQKVN4atZecAla2Hxr8IBIB8islqDvqY+42vbR+tMeDKMman9+FUoAqMzE0OnB8VIbM1QY0w==}
'@prisma/client@6.19.2':
resolution: {integrity: sha512-gR2EMvfK/aTxsuooaDA32D8v+us/8AAet+C3J1cc04SW35FPdZYgLF+iN4NDLUgAaUGTKdAB0CYenu1TAgGdMg==}
@@ -1450,8 +2013,8 @@ packages:
'@prisma/get-platform@6.19.2':
resolution: {integrity: sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==}
- '@prisma/instrumentation@7.2.0':
- resolution: {integrity: sha512-Rh9Z4x5kEj1OdARd7U18AtVrnL6rmLSI0qYShaB4W7Wx5BKbgzndWF+QnuzMb7GLfVdlT5aYCXoPQVYuYtVu0g==}
+ '@prisma/instrumentation@7.4.2':
+ resolution: {integrity: sha512-r9JfchJF1Ae6yAxcaLu/V1TGqBhAuSDe3mRNOssBfx1rMzfZ4fdNvrgUBwyb/TNTGXFxlH9AZix5P257x07nrg==}
peerDependencies:
'@opentelemetry/api': ^1.8
@@ -1485,6 +2048,17 @@ packages:
'@protobufjs/utf8@1.1.0':
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
+ '@reduxjs/toolkit@2.11.2':
+ resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==}
+ peerDependencies:
+ react: ^16.9.0 || ^17.0.0 || ^18 || ^19
+ react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-redux:
+ optional: true
+
'@rollup/plugin-commonjs@28.0.1':
resolution: {integrity: sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==}
engines: {node: '>=16.0.0 || 14 >= 14.17'}
@@ -1634,28 +2208,28 @@ packages:
'@schummar/icu-type-parser@1.21.5':
resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
- '@sentry-internal/browser-utils@10.43.0':
- resolution: {integrity: sha512-8zYTnzhAPvNkVH1Irs62wl0J/c+0QcJ62TonKnzpSFUUD3V5qz8YDZbjIDGfxy+1EB9fO0sxtddKCzwTHF/MbQ==}
+ '@sentry-internal/browser-utils@10.45.0':
+ resolution: {integrity: sha512-ZPZpeIarXKScvquGx2AfNKcYiVNDA4wegMmjyGVsTA2JPmP0TrJoO3UybJS6KGDeee8V3I3EfD/ruauMm7jOFQ==}
engines: {node: '>=18'}
- '@sentry-internal/feedback@10.43.0':
- resolution: {integrity: sha512-YoXuwluP6eOcQxTeTtaWb090++MrLyWOVsUTejzUQQ6LFL13Jwt+bDPF1kvBugMq4a7OHw/UNKQfd6//rZMn2g==}
+ '@sentry-internal/feedback@10.45.0':
+ resolution: {integrity: sha512-vCSurazFVq7RUeYiM5X326jA5gOVrWYD6lYX2fbjBOMcyCEhDnveNxMT62zKkZDyNT/jyD194nz/cjntBUkyWA==}
engines: {node: '>=18'}
- '@sentry-internal/replay-canvas@10.43.0':
- resolution: {integrity: sha512-ZIw1UNKOFXo1LbPCJPMAx9xv7D8TMZQusLDUgb6BsPQJj0igAuwd7KRGTkjjgnrwBp2O/sxcQFRhQhknWk7QPg==}
+ '@sentry-internal/replay-canvas@10.45.0':
+ resolution: {integrity: sha512-nvq/AocdZTuD7y0KSiWi3gVaY0s5HOFy86mC/v1kDZmT/jsBAzN5LDkk/f1FvsWma1peqQmpUqxvhC+YIW294Q==}
engines: {node: '>=18'}
- '@sentry-internal/replay@10.43.0':
- resolution: {integrity: sha512-khCXlGrlH1IU7P5zCEAJFestMeH97zDVCekj8OsNNDtN/1BmCJ46k6Xi0EqAUzdJgrOLJeLdoYdgtiIjovZ8Sg==}
+ '@sentry-internal/replay@10.45.0':
+ resolution: {integrity: sha512-vjosRoGA1bzhVAEO1oce+CsRdd70quzBeo7WvYqpcUnoLe/Rv8qpOMqWX3j26z7XfFHMExWQNQeLxmtYOArvlw==}
engines: {node: '>=18'}
'@sentry/babel-plugin-component-annotate@5.1.1':
resolution: {integrity: sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg==}
engines: {node: '>= 18'}
- '@sentry/browser@10.43.0':
- resolution: {integrity: sha512-2V3I3sXi3SMeiZpKixd9ztokSgK27cmvsD9J5oyOyjhGLTW/6QKCwHbKnluMgQMXq20nixQk5zN4wRjRUma3sg==}
+ '@sentry/browser@10.45.0':
+ resolution: {integrity: sha512-e/a8UMiQhqqv706McSIcG6XK+AoQf9INthi2pD+giZfNRTzXTdqHzUT5OIO5hg8Am6eF63nDJc+vrYNPhzs51Q==}
engines: {node: '>=18'}
'@sentry/bundler-plugin-core@5.1.1':
@@ -1714,18 +2288,18 @@ packages:
engines: {node: '>= 10'}
hasBin: true
- '@sentry/core@10.43.0':
- resolution: {integrity: sha512-l0SszQAPiQGWl/ferw8GP3ALyHXiGiRKJaOvNmhGO+PrTQyZTZ6OYyPnGijAFRg58dE1V3RCH/zw5d2xSUIiNg==}
+ '@sentry/core@10.45.0':
+ resolution: {integrity: sha512-s69UXxvefeQxuZ5nY7/THtTrIEvJxNVCp3ns4kwoCw1qMpgpvn/296WCKVmM7MiwnaAdzEKnAvLAwaxZc2nM7Q==}
engines: {node: '>=18'}
- '@sentry/nextjs@10.43.0':
- resolution: {integrity: sha512-SmybDiZdI4c7GQYvi+HNBKbnKOmIaiqsLj67vVVV0tN6A1iX9OrP5jldxawzrd9wn5oXDhHSyzJmyKwdOu7/MQ==}
+ '@sentry/nextjs@10.45.0':
+ resolution: {integrity: sha512-4LE+UvnfdOYyG8YEb/9TWaJQzMPuGLlph/iqowvsMdxaW6la+mvADiuzNTXly4QfsjeD3KIb7dKlGTqiVV0Ttw==}
engines: {node: '>=18'}
peerDependencies:
next: ^13.2.0 || ^14.0 || ^15.0.0-rc.0 || ^16.0.0-0
- '@sentry/node-core@10.43.0':
- resolution: {integrity: sha512-w2H3NSkNMoYOS7o7mR55BM7+xL++dPxMSv1/XDfsra9FYHGppO+Mxk667Ee5k+uDi+wNIioICIh+5XOvZh4+HQ==}
+ '@sentry/node-core@10.45.0':
+ resolution: {integrity: sha512-KQZEvLKM344+EqXiA9HIzWbW5hzq6/9nnFUQ8niaBPoOgR9AiJhrccfIscfgb8vjkriiEtzE03OW/4h1CTgZ3Q==}
engines: {node: '>=18'}
peerDependencies:
'@opentelemetry/api': ^1.9.0
@@ -1751,12 +2325,12 @@ packages:
'@opentelemetry/semantic-conventions':
optional: true
- '@sentry/node@10.43.0':
- resolution: {integrity: sha512-oNwXcuZUc4uTTr0WbHZBBIKsKwAKvNMTgbXwxfB37CfzV18wbTirbQABZ/Ir3WNxSgi6ZcnC6UE013jF5XWPqw==}
+ '@sentry/node@10.45.0':
+ resolution: {integrity: sha512-Kpiq9lRGnJc1ex8SwxOBl+FLQNl4Y137BydVooP7AFiAYZ6ftwHsIEF1bcYXaipHMT1YHS2bdhC2UQaaB2jkuQ==}
engines: {node: '>=18'}
- '@sentry/opentelemetry@10.43.0':
- resolution: {integrity: sha512-+fIcnnLdvBHdq4nKq23t9v/B9D4L97fPWEDksXbpGs11o6BsqY4Tlzmce6cP95iiQhPckCEag3FthSND+BYtYQ==}
+ '@sentry/opentelemetry@10.45.0':
+ resolution: {integrity: sha512-PmuGO+p/gC3ZQ8ddOeJ5P9ApnTTm35i12Bpuyb13AckCbNSJFvG2ggZda35JQOmiFU0kKYiwkoFAa8Mvj9od3Q==}
engines: {node: '>=18'}
peerDependencies:
'@opentelemetry/api': ^1.9.0
@@ -1765,14 +2339,14 @@ packages:
'@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
'@opentelemetry/semantic-conventions': ^1.39.0
- '@sentry/react@10.43.0':
- resolution: {integrity: sha512-shvErEpJ41i0Q3lIZl0CDWYQ7m8yHLi7ECG0gFvN8zf8pEdl5grQIOoe3t/GIUzcpCcor16F148ATmKJJypc/Q==}
+ '@sentry/react@10.45.0':
+ resolution: {integrity: sha512-jLezuxi4BUIU3raKyAPR5xMbQG/nhwnWmKo5p11NCbLmWzkS+lxoyDTUB4B8TAKZLfdtdkKLOn1S0tFc8vbUHw==}
engines: {node: '>=18'}
peerDependencies:
react: ^16.14.0 || 17.x || 18.x || 19.x
- '@sentry/vercel-edge@10.43.0':
- resolution: {integrity: sha512-souwH0QGKh2KE5ZH1ZYii1dbT5qsCP1VN+wpIG89ui85+eSmUQfakIjyS2Trs6JfxZ9TIYmmBTkWE9ziEseItg==}
+ '@sentry/vercel-edge@10.45.0':
+ resolution: {integrity: sha512-sSF+Ex5NwT60gMinLcP/JNZb3cDaIv0mL1cRjfvN6zN2ZNEw0C9rhdgxa0EdD4G6PCHQ0XnCuAMDsfJ6gnRmfA==}
engines: {node: '>=18'}
'@sentry/webpack-plugin@5.1.1':
@@ -1781,12 +2355,36 @@ packages:
peerDependencies:
webpack: '>=5.0.0'
+ '@shikijs/core@3.23.0':
+ resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==}
+
+ '@shikijs/engine-javascript@3.23.0':
+ resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==}
+
+ '@shikijs/engine-oniguruma@3.23.0':
+ resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==}
+
+ '@shikijs/langs@3.23.0':
+ resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==}
+
+ '@shikijs/themes@3.23.0':
+ resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==}
+
+ '@shikijs/types@3.23.0':
+ resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
'@stablelib/base64@1.0.1':
resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+ '@standard-schema/utils@0.3.0':
+ resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
+
'@swc/core-darwin-arm64@1.15.18':
resolution: {integrity: sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==}
engines: {node: '>=10'}
@@ -1862,9 +2460,52 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
+ '@swc/helpers@0.5.19':
+ resolution: {integrity: sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA==}
+
'@swc/types@0.1.25':
resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==}
+ '@tokenizer/inflate@0.4.1':
+ resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==}
+ engines: {node: '>=18'}
+
+ '@tokenizer/token@0.3.0':
+ resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
+
+ '@tootallnate/quickjs-emscripten@0.23.0':
+ resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
+
+ '@turbo/darwin-64@2.8.20':
+ resolution: {integrity: sha512-FQ9EX1xMU5nbwjxXxM3yU88AQQ6Sqc6S44exPRroMcx9XZHqqppl5ymJF0Ig/z3nvQNwDmz1Gsnvxubo+nXWjQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@turbo/darwin-arm64@2.8.20':
+ resolution: {integrity: sha512-Gpyh9ATFGThD6/s9L95YWY54cizg/VRWl2B67h0yofG8BpHf67DFAh9nuJVKG7bY0+SBJDAo5cMur+wOl9YOYw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@turbo/linux-64@2.8.20':
+ resolution: {integrity: sha512-p2QxWUYyYUgUFG0b0kR+pPi8t7c9uaVlRtjTTI1AbCvVqkpjUfCcReBn6DgG/Hu8xrWdKLuyQFaLYFzQskZbcA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@turbo/linux-arm64@2.8.20':
+ resolution: {integrity: sha512-Gn5yjlZGLRZWarLWqdQzv0wMqyBNIdq1QLi48F1oY5Lo9kiohuf7BPQWtWxeNVS2NgJ1+nb/DzK1JduYC4AWOA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@turbo/windows-64@2.8.20':
+ resolution: {integrity: sha512-vyaDpYk/8T6Qz5V/X+ihKvKFEZFUoC0oxYpC1sZanK6gaESJlmV3cMRT3Qhcg4D2VxvtC2Jjs9IRkrZGL+exLw==}
+ cpu: [x64]
+ os: [win32]
+
+ '@turbo/windows-arm64@2.8.20':
+ resolution: {integrity: sha512-voicVULvUV5yaGXo0Iue13BcHGYW3u0VgqSbfQwBaHbpj1zLjYV4KIe+7fYIo6DO8FVUJzxFps3ODCQG/Wy2Qw==}
+ cpu: [arm64]
+ os: [win32]
+
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
@@ -1875,33 +2516,102 @@ packages:
resolution: {integrity: sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg==}
deprecated: This is a stub types definition. bcryptjs provides its own type definitions, so you do not need this installed.
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
'@types/connect@3.4.38':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
+ '@types/d3-array@3.2.2':
+ resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
+
+ '@types/d3-color@3.1.3':
+ resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
+
+ '@types/d3-ease@3.0.2':
+ resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
+
+ '@types/d3-interpolate@3.0.4':
+ resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
+
+ '@types/d3-path@3.1.1':
+ resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
+
+ '@types/d3-scale@4.0.9':
+ resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
+
+ '@types/d3-shape@3.1.8':
+ resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==}
+
+ '@types/d3-time@3.0.4':
+ resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
+
+ '@types/d3-timer@3.0.2':
+ resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
+
+ '@types/debug@4.1.12':
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
'@types/eslint-scope@3.7.7':
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
'@types/eslint@9.6.1':
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/geoip-lite@1.4.4':
+ resolution: {integrity: sha512-2uVfn+C6bX/H356H6mjxsWUA5u8LO8dJgSBIRO/NFlpMe4DESzacutD/rKYrTDKm1Ugv78b4Wz1KvpHrlv3jSw==}
+
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
+ '@types/js-yaml@4.0.9':
+ resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+ '@types/mdx@2.0.13':
+ resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
+
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
+ '@types/mute-stream@0.0.4':
+ resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==}
+
'@types/mysql@2.15.27':
resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==}
+ '@types/nlcst@2.0.3':
+ resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
+
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
'@types/node@20.19.37':
resolution: {integrity: sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==}
+ '@types/node@24.12.0':
+ resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==}
+
+ '@types/node@25.5.0':
+ resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==}
+
'@types/pdfkit@0.17.5':
resolution: {integrity: sha512-T3ZHnvF91HsEco5ClhBCOuBwobZfPcI2jaiSHybkkKYq4KhVIIurod94JVKvDIG0JXT6o3KiERC0X0//m8dyrg==}
@@ -1925,71 +2635,89 @@ packages:
'@types/readdir-glob@1.1.5':
resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==}
+ '@types/sax@1.2.7':
+ resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
+
'@types/tedious@4.0.14':
resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
- '@typescript-eslint/eslint-plugin@8.56.1':
- resolution: {integrity: sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==}
+ '@types/unist@2.0.11':
+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
+ '@types/use-sync-external-store@0.0.6':
+ resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
+
+ '@types/wrap-ansi@3.0.0':
+ resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==}
+
+ '@typescript-eslint/eslint-plugin@8.57.2':
+ resolution: {integrity: sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.56.1
+ '@typescript-eslint/parser': ^8.57.2
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/parser@8.56.1':
- resolution: {integrity: sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==}
+ '@typescript-eslint/parser@8.57.2':
+ resolution: {integrity: sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/project-service@8.56.1':
- resolution: {integrity: sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==}
+ '@typescript-eslint/project-service@8.57.2':
+ resolution: {integrity: sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/scope-manager@8.56.1':
- resolution: {integrity: sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==}
+ '@typescript-eslint/scope-manager@8.57.2':
+ resolution: {integrity: sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.56.1':
- resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==}
+ '@typescript-eslint/tsconfig-utils@8.57.2':
+ resolution: {integrity: sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/type-utils@8.56.1':
- resolution: {integrity: sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==}
+ '@typescript-eslint/type-utils@8.57.2':
+ resolution: {integrity: sha512-Co6ZCShm6kIbAM/s+oYVpKFfW7LBc6FXoPXjTRQ449PPNBY8U0KZXuevz5IFuuUj2H9ss40atTaf9dlGLzbWZg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/types@8.56.1':
- resolution: {integrity: sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==}
+ '@typescript-eslint/types@8.57.2':
+ resolution: {integrity: sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.56.1':
- resolution: {integrity: sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==}
+ '@typescript-eslint/typescript-estree@8.57.2':
+ resolution: {integrity: sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/utils@8.56.1':
- resolution: {integrity: sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==}
+ '@typescript-eslint/utils@8.57.2':
+ resolution: {integrity: sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/visitor-keys@8.56.1':
- resolution: {integrity: sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==}
+ '@typescript-eslint/visitor-keys@8.57.2':
+ resolution: {integrity: sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@ungap/structured-clone@1.3.0':
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
cpu: [arm]
@@ -2088,6 +2816,9 @@ packages:
'@vitest/expect@2.1.9':
resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
+ '@vitest/expect@4.1.0':
+ resolution: {integrity: sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==}
+
'@vitest/mocker@2.1.9':
resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
peerDependencies:
@@ -2099,21 +2830,73 @@ packages:
vite:
optional: true
+ '@vitest/mocker@4.1.0':
+ resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
'@vitest/pretty-format@2.1.9':
resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
+ '@vitest/pretty-format@4.1.0':
+ resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==}
+
'@vitest/runner@2.1.9':
resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
+ '@vitest/runner@4.1.0':
+ resolution: {integrity: sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==}
+
'@vitest/snapshot@2.1.9':
resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
+ '@vitest/snapshot@4.1.0':
+ resolution: {integrity: sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==}
+
'@vitest/spy@2.1.9':
resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
+ '@vitest/spy@4.1.0':
+ resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==}
+
'@vitest/utils@2.1.9':
resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
+ '@vitest/utils@4.1.0':
+ resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==}
+
+ '@volar/kit@2.4.28':
+ resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==}
+ peerDependencies:
+ typescript: '*'
+
+ '@volar/language-core@2.4.28':
+ resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==}
+
+ '@volar/language-server@2.4.28':
+ resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==}
+
+ '@volar/language-service@2.4.28':
+ resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==}
+
+ '@volar/source-map@2.4.28':
+ resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==}
+
+ '@volar/typescript@2.4.28':
+ resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==}
+
+ '@vscode/emmet-helper@2.11.0':
+ resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==}
+
+ '@vscode/l10n@0.0.18':
+ resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}
+
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
@@ -2159,6 +2942,10 @@ packages:
'@webassemblyjs/wast-printer@1.14.1':
resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==}
+ '@xmldom/xmldom@0.8.11':
+ resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
+ engines: {node: '>=10.0.0'}
+
'@xtuc/ieee754@1.2.0':
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
@@ -2197,6 +2984,18 @@ packages:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ ajv-draft-04@1.0.0:
+ resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
+ peerDependencies:
+ ajv: ^8.5.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -2224,10 +3023,17 @@ packages:
ajv@8.18.0:
resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==}
+ ansi-align@3.0.1:
+ resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
+
ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
+ ansi-escapes@4.3.2:
+ resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+ engines: {node: '>=8'}
+
ansi-escapes@7.3.0:
resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==}
engines: {node: '>=18'}
@@ -2251,6 +3057,10 @@ packages:
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
archiver-utils@5.0.2:
resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==}
engines: {node: '>= 14'}
@@ -2259,6 +3069,9 @@ packages:
resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==}
engines: {node: '>= 14'}
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
@@ -2277,6 +3090,9 @@ packages:
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
engines: {node: '>= 0.4'}
+ array-iterate@2.0.1:
+ resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
+
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
@@ -2315,6 +3131,24 @@ packages:
ast-types-flow@0.0.8:
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+ ast-types@0.13.4:
+ resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
+ engines: {node: '>=4'}
+
+ astring@1.9.0:
+ resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
+ hasBin: true
+
+ astro-expressive-code@0.41.7:
+ resolution: {integrity: sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ==}
+ peerDependencies:
+ astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta
+
+ astro@5.18.1:
+ resolution: {integrity: sha512-m4VWilWZ+Xt6NPoYzC4CgGZim/zQUO7WFL0RHCH0AiEavF1153iC3+me2atDvXpf/yX4PyGUeD8wZLq1cirT3g==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
+ hasBin: true
+
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -2355,6 +3189,9 @@ packages:
react-native-b4a:
optional: true
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -2400,6 +3237,9 @@ packages:
bare-url@2.3.2:
resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==}
+ base-64@1.0.0:
+ resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
+
base64-js@0.0.8:
resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==}
engines: {node: '>= 0.4'}
@@ -2407,11 +3247,21 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
- baseline-browser-mapping@2.10.0:
- resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==}
+ baseline-browser-mapping@2.10.9:
+ resolution: {integrity: sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==}
engines: {node: '>=6.0.0'}
hasBin: true
+ basic-ftp@5.2.0:
+ resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==}
+ engines: {node: '>=10.0.0'}
+
+ bcp-47-match@2.0.3:
+ resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==}
+
+ bcp-47@2.1.0:
+ resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==}
+
bcryptjs@3.0.3:
resolution: {integrity: sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==}
hasBin: true
@@ -2420,9 +3270,19 @@ packages:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
+ bluebird@3.7.2:
+ resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+
bn.js@4.12.3:
resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==}
+ boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+
+ boxen@8.0.1:
+ resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==}
+ engines: {node: '>=18'}
+
brace-expansion@1.1.12:
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
@@ -2445,6 +3305,9 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+
buffer-crc32@1.0.0:
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
engines: {node: '>=8.0.0'}
@@ -2493,21 +3356,48 @@ packages:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
- caniuse-lite@1.0.30001777:
- resolution: {integrity: sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==}
+ camelcase@8.0.0:
+ resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==}
+ engines: {node: '>=16'}
+
+ caniuse-lite@1.0.30001780:
+ resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
- ccxt@4.5.42:
- resolution: {integrity: sha512-7TKtOOnAheWzNtZHSBjuGKIbt5CRDJAyybyrYnj6moZsK9TXBmxPJbQIBAWKCmcOCkddIZRf1K6gKKFMQO9eyA==}
+ ccxt@4.5.44:
+ resolution: {integrity: sha512-cumeM+Mmb2Gj103G7q3oyjLoJ6Wf8JGwdVZO2y9QSg2RVHWgTSTcZehJt4Etj44k39X82tVPSI4+w3zvHVgAjQ==}
engines: {node: '>=15.0.0'}
chai@5.3.3:
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
engines: {node: '>=18'}
+ chai@6.2.2:
+ resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
+ engines: {node: '>=18'}
+
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
+ chalk@5.6.2:
+ resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+ character-reference-invalid@2.0.1:
+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
chardet@2.1.1:
resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==}
@@ -2519,10 +3409,18 @@ packages:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
+ chokidar@5.0.0:
+ resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
+ engines: {node: '>= 20.19.0'}
+
chrome-trace-event@1.0.4:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'}
+ ci-info@4.4.0:
+ resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==}
+ engines: {node: '>=8'}
+
citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
@@ -2532,24 +3430,51 @@ packages:
cjs-module-lexer@2.2.0:
resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==}
+ cli-boxes@3.0.0:
+ resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
+ engines: {node: '>=10'}
+
cli-cursor@5.0.0:
resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
engines: {node: '>=18'}
+ cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+
cli-truncate@5.2.0:
resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==}
engines: {node: '>=20'}
+ cli-width@4.1.0:
+ resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
+ engines: {node: '>= 12'}
+
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ clone@1.0.4:
+ resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
+ engines: {node: '>=0.8'}
+
clone@2.1.2:
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
engines: {node: '>=0.8'}
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ collapse-white-space@2.1.0:
+ resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -2557,6 +3482,13 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ color-string@1.9.1:
+ resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+
+ color@4.2.3:
+ resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
+ engines: {node: '>=12.5.0'}
+
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
@@ -2564,6 +3496,13 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
+ commander@11.1.0:
+ resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
+ engines: {node: '>=16'}
+
commander@14.0.3:
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
engines: {node: '>=20'}
@@ -2575,9 +3514,19 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
+ commander@8.3.0:
+ resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
+ engines: {node: '>= 12'}
+
+ common-ancestor-path@1.0.1:
+ resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
+
commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+ compare-versions@6.1.1:
+ resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
+
compress-commons@6.0.2:
resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==}
engines: {node: '>= 14'}
@@ -2585,16 +3534,28 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ concurrently@9.2.1:
+ resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==}
+ engines: {node: '>=18'}
+ hasBin: true
+
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
confbox@0.2.4:
resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==}
+ consola@2.15.3:
+ resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
+
consola@3.4.2:
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
engines: {node: ^14.18.0 || >=16.10.0}
+ console.table@0.10.0:
+ resolution: {integrity: sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==}
+ engines: {node: '> 0.10'}
+
content-disposition@1.0.1:
resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==}
engines: {node: '>=18'}
@@ -2602,12 +3563,15 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie-es@1.2.2:
+ resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
+
cookie@1.1.1:
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
engines: {node: '>=18'}
- core-js@3.48.0:
- resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==}
+ core-js@3.49.0:
+ resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -2625,15 +3589,90 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
- crypto-js@4.2.0:
- resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
+ crossws@0.3.5:
+ resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
+
+ css-select@5.2.2:
+ resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
+
+ css-selector-parser@3.3.0:
+ resolution: {integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==}
+
+ css-tree@2.2.1:
+ resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
+ css-tree@3.2.1:
+ resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
+ css-what@6.2.2:
+ resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
+ engines: {node: '>= 6'}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ csso@5.0.5:
+ resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+
+ d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+
+ d3-ease@3.0.1:
+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+ engines: {node: '>=12'}
+
+ d3-format@3.1.2:
+ resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
+ engines: {node: '>=12'}
+
+ d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+
+ d3-path@3.1.0:
+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+ engines: {node: '>=12'}
+
+ d3-scale@4.0.2:
+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+ engines: {node: '>=12'}
+
+ d3-shape@3.2.0:
+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+ engines: {node: '>=12'}
+
+ d3-time-format@4.1.0:
+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+ engines: {node: '>=12'}
+
+ d3-time@3.1.0:
+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+ engines: {node: '>=12'}
+
+ d3-timer@3.0.1:
+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+ engines: {node: '>=12'}
+
damerau-levenshtein@1.0.8:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+ data-uri-to-buffer@6.0.2:
+ resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
+ engines: {node: '>= 14'}
+
data-view-buffer@1.0.2:
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
@@ -2673,9 +3712,15 @@ packages:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
+ decimal.js-light@2.5.1:
+ resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
+
decimal.js@10.6.0:
resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+ decode-named-character-reference@1.3.0:
+ resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
+
deep-eql@5.0.2:
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
engines: {node: '>=6'}
@@ -2687,6 +3732,9 @@ packages:
resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==}
engines: {node: '>=16.0.0'}
+ defaults@1.0.4:
+ resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
+
define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
@@ -2698,6 +3746,10 @@ packages:
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+ degenerator@5.0.1:
+ resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
+ engines: {node: '>= 14'}
+
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -2721,9 +3773,23 @@ packages:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ deterministic-object-hash@2.0.2:
+ resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==}
+ engines: {node: '>=18'}
+
+ devalue@5.6.4:
+ resolution: {integrity: sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
dfa@1.2.0:
resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==}
+ diff@8.0.3:
+ resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==}
+ engines: {node: '>=0.3.1'}
+
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
@@ -2731,36 +3797,73 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
+ direction@2.0.1:
+ resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==}
+ hasBin: true
+
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
doctrine@2.1.0:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
+ dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
+ domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+ domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+
dompurify@3.3.3:
resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==}
+ domutils@3.2.2:
+ resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+
dotenv@16.6.1:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
+ dotenv@17.3.1:
+ resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==}
+ engines: {node: '>=12'}
+
dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
engines: {node: '>=10'}
+ dset@3.1.4:
+ resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
+ engines: {node: '>=4'}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+ duplexer2@0.1.4:
+ resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ easy-table@1.1.0:
+ resolution: {integrity: sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==}
+
ecdsa-sig-formatter@1.0.11:
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
effect@3.18.4:
resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==}
- electron-to-chromium@1.5.307:
- resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==}
+ electron-to-chromium@1.5.321:
+ resolution: {integrity: sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==}
+
+ emmet@2.4.11:
+ resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==}
emoji-regex@10.6.0:
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
@@ -2778,14 +3881,22 @@ packages:
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
- enhanced-resolve@5.20.0:
- resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==}
+ enhanced-resolve@5.20.1:
+ resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
engines: {node: '>=10.13.0'}
enquirer@2.4.1:
resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
engines: {node: '>=8.6'}
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
environment@1.1.0:
resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
engines: {node: '>=18'}
@@ -2802,8 +3913,8 @@ packages:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
- es-iterator-helpers@1.2.2:
- resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==}
+ es-iterator-helpers@1.3.1:
+ resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==}
engines: {node: '>= 0.4'}
es-module-lexer@1.7.0:
@@ -2828,11 +3939,25 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
+ es-toolkit@1.45.1:
+ resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==}
+
+ esast-util-from-estree@2.0.0:
+ resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
+
+ esast-util-from-js@2.0.1:
+ resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
+
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
hasBin: true
+ esbuild@0.25.12:
+ resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
esbuild@0.27.3:
resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
engines: {node: '>=18'}
@@ -2845,12 +3970,25 @@ packages:
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+ escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
- eslint-config-next@16.1.6:
- resolution: {integrity: sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==}
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
+ escodegen@2.1.0:
+ resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
+ engines: {node: '>=6.0'}
+ hasBin: true
+
+ eslint-config-next@16.2.0:
+ resolution: {integrity: sha512-LlVJrWnjIkgQRECjIOELyAtrWFqzn326ARS5ap7swc1YKL4wkry6/gszn6wi5ZDWKxKe7fanxArvhqMoAzbL7w==}
peerDependencies:
eslint: '>=9.0.0'
typescript: '>=3.3.1'
@@ -2978,6 +4116,24 @@ packages:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
+ estree-util-attach-comments@3.0.0:
+ resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
+
+ estree-util-build-jsx@3.0.1:
+ resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
+ estree-util-scope@1.0.0:
+ resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
+
+ estree-util-to-js@2.0.0:
+ resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
+
+ estree-util-visit@2.0.0:
+ resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
+
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@@ -3006,9 +4162,19 @@ packages:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
+ expressive-code@0.41.7:
+ resolution: {integrity: sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA==}
+
exsolve@1.0.8:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
+ extend-shallow@2.0.1:
+ resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
+ engines: {node: '>=0.10.0'}
+
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
extendable-error@0.1.7:
resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
@@ -3032,6 +4198,10 @@ packages:
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
engines: {node: '>=8.6.0'}
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
@@ -3064,23 +4234,22 @@ packages:
fastify-plugin@5.1.0:
resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==}
- fastify-zod-openapi@4.1.2:
- resolution: {integrity: sha512-7dcrgMqu862tL5WoSxgZAuxsx4ce0cBTdG9pOGEOc58k7Ti9Cub0xNbzy+o3S8vZFmq4nSqFrDTFSxXwLLJ16A==}
+ fastify-zod-openapi@5.5.0:
+ resolution: {integrity: sha512-b6AhZuz68AiywJxTkxTGtBQonrgxp6udRRKapcimBn4b8iBulQmMYmjjwe8FKwY8LMAXbf8lPPfgwC6apWPa/g==}
engines: {node: '>=20'}
peerDependencies:
'@fastify/swagger': ^9.0.0
'@fastify/swagger-ui': ^5.0.1
fastify: '5'
- zod: ^3.21.4
- zod-openapi: ^4.2.0
+ zod: ^3.25.74 || ^4.0.0
peerDependenciesMeta:
'@fastify/swagger':
optional: true
'@fastify/swagger-ui':
optional: true
- fastify@5.8.1:
- resolution: {integrity: sha512-y0kicFvvn7CYWoPOVLOcvn4YyKQz03DIY7UxmyOy21/J8eXm09R+tmb+tVDBW5h+pja30cHI5dqUcSlvY86V2A==}
+ fastify@5.8.2:
+ resolution: {integrity: sha512-lZmt3navvZG915IE+f7/TIVamxIwmBd+OMB+O9WBzcpIwOo6F0LTh0sluoMFk5VkrKTvvrwIaoJPkir4Z+jtAg==}
fastparallel@2.4.1:
resolution: {integrity: sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==}
@@ -3103,10 +4272,21 @@ packages:
fflate@0.4.8:
resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
+ fflate@0.8.2:
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
+
+ figures@3.2.0:
+ resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
+ engines: {node: '>=8'}
+
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
+ file-type@21.3.0:
+ resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==}
+ engines: {node: '>=20'}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
@@ -3130,8 +4310,12 @@ packages:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'}
- flatted@3.3.4:
- resolution: {integrity: sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==}
+ flatted@3.4.2:
+ resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
+
+ flattie@1.1.1:
+ resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
+ engines: {node: '>=8'}
follow-redirects@1.15.11:
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
@@ -3142,9 +4326,16 @@ packages:
debug:
optional: true
+ fontace@0.4.1:
+ resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==}
+
fontkit@2.0.4:
resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==}
+ fontkitten@1.0.3:
+ resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
+ engines: {node: '>=20'}
+
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
@@ -3160,6 +4351,10 @@ packages:
forwarded-parse@2.1.2:
resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
+ fs-extra@11.3.4:
+ resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==}
+ engines: {node: '>=14.14'}
+
fs-extra@7.0.1:
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
engines: {node: '>=6 <7 || >=8'}
@@ -3196,6 +4391,10 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ geoip-lite@2.0.1:
+ resolution: {integrity: sha512-cR9E28nu1a6dsvzB1tANhdmCyXWV1L4AiSCT9alHLIUl06599EGu33mqY99ieU0twQob0kfcDQ/sAUBvHb7swA==}
+ engines: {node: '>=24.0.0'}
+
get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
@@ -3219,10 +4418,17 @@ packages:
get-tsconfig@4.13.6:
resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==}
+ get-uri@6.0.5:
+ resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==}
+ engines: {node: '>= 14'}
+
giget@2.0.0:
resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
hasBin: true
+ github-slugger@2.0.0:
+ resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -3266,6 +4472,13 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ gray-matter@4.0.3:
+ resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
+ engines: {node: '>=6.0'}
+
+ h3@1.15.9:
+ resolution: {integrity: sha512-H7UPnyIupUOYUQu7f2x7ABVeMyF/IbJjqn20WSXpMdnQB260luADUkSgJU7QTWLutq8h3tUayMQ1DdbSYX5LkA==}
+
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -3293,6 +4506,66 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-embedded@3.0.0:
+ resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==}
+
+ hast-util-format@1.1.0:
+ resolution: {integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==}
+
+ hast-util-from-html@2.0.3:
+ resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}
+
+ hast-util-from-parse5@8.0.3:
+ resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
+
+ hast-util-has-property@3.0.0:
+ resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==}
+
+ hast-util-is-body-ok-link@3.0.1:
+ resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==}
+
+ hast-util-is-element@3.0.0:
+ resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
+
+ hast-util-minify-whitespace@1.0.1:
+ resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==}
+
+ hast-util-parse-selector@4.0.0:
+ resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
+
+ hast-util-phrasing@3.0.1:
+ resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==}
+
+ hast-util-raw@9.1.0:
+ resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}
+
+ hast-util-select@6.0.4:
+ resolution: {integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==}
+
+ hast-util-to-estree@3.1.3:
+ resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
+
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-to-parse5@8.0.1:
+ resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}
+
+ hast-util-to-string@3.0.1:
+ resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}
+
+ hast-util-to-text@4.0.2:
+ resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ hastscript@9.0.1:
+ resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
+
help-me@5.0.0:
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
@@ -3302,14 +4575,37 @@ packages:
hermes-parser@0.25.1:
resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+ html-escaper@3.0.3:
+ resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
+
+ html-url-attributes@3.0.1:
+ resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ html-whitespace-sensitive-tag-names@3.0.1:
+ resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==}
+
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
+
http-errors@2.0.1:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'}
+ http-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ engines: {node: '>= 14'}
+
https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
human-id@4.1.3:
resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==}
hasBin: true
@@ -3319,6 +4615,13 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ i18next@23.16.8:
+ resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
iconv-lite@0.7.2:
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
engines: {node: '>=0.10.0'}
@@ -3337,6 +4640,12 @@ packages:
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
+ immer@10.2.0:
+ resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==}
+
+ immer@11.1.4:
+ resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==}
+
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
@@ -3344,6 +4653,13 @@ packages:
import-in-the-middle@2.0.6:
resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==}
+ import-in-the-middle@3.0.0:
+ resolution: {integrity: sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg==}
+ engines: {node: '>=18'}
+
+ import-meta-resolve@4.2.0:
+ resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
+
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -3351,21 +4667,48 @@ packages:
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
+ internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+
intl-messageformat@11.1.2:
resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==}
+ ip-address@10.1.0:
+ resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
+ engines: {node: '>= 12'}
+
+ ip-address@5.9.4:
+ resolution: {integrity: sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==}
+ engines: {node: '>= 0.10'}
+
ipaddr.js@2.3.0:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'}
+ iron-webcrypto@1.2.1:
+ resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
+
+ is-alphabetical@2.0.1:
+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+ is-alphanumerical@2.0.1:
+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
is-array-buffer@3.0.5:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
+ is-arrayish@0.3.4:
+ resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==}
+
is-async-function@2.1.1:
resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
engines: {node: '>= 0.4'}
@@ -3397,6 +4740,18 @@ packages:
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
+ is-decimal@2.0.1:
+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
+ is-extendable@0.1.1:
+ resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
+ engines: {node: '>=0.10.0'}
+
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3421,6 +4776,14 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
+ is-hexadecimal@2.0.1:
+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
is-map@2.0.3:
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
engines: {node: '>= 0.4'}
@@ -3437,6 +4800,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
is-reference@1.2.1:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
@@ -3488,6 +4855,10 @@ packages:
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
engines: {node: '>=0.10.0'}
+ is-wsl@3.1.1:
+ resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
+ engines: {node: '>=16'}
+
isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
@@ -3497,6 +4868,10 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ iterare@1.2.1:
+ resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
+ engines: {node: '>=6'}
+
iterator.prototype@1.1.5:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
@@ -3516,9 +4891,8 @@ packages:
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
engines: {node: '>=10'}
- jpeg-exif@1.1.4:
- resolution: {integrity: sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==}
- deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+ js-md5@0.8.3:
+ resolution: {integrity: sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==}
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -3531,6 +4905,9 @@ packages:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
+ jsbn@1.1.0:
+ resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
+
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -3571,9 +4948,18 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jsonc-parser@2.3.1:
+ resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==}
+
+ jsonc-parser@3.3.1:
+ resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
+
jsonfile@4.0.0:
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+ jsonfile@6.2.0:
+ resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
+
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
@@ -3581,6 +4967,22 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
+ kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+
+ klona@2.0.6:
+ resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==}
+ engines: {node: '>= 8'}
+
language-subtag-registry@0.3.23:
resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
@@ -3588,6 +4990,10 @@ packages:
resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
engines: {node: '>=0.10'}
+ lazy@1.0.11:
+ resolution: {integrity: sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==}
+ engines: {node: '>=0.2.0'}
+
lazystream@1.0.1:
resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==}
engines: {node: '>= 0.6.3'}
@@ -3609,8 +5015,8 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
- lint-staged@16.3.2:
- resolution: {integrity: sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==}
+ lint-staged@16.4.0:
+ resolution: {integrity: sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==}
engines: {node: '>=20.17'}
hasBin: true
@@ -3618,6 +5024,10 @@ packages:
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
engines: {node: '>=20.0.0'}
+ load-esm@1.0.3:
+ resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==}
+ engines: {node: '>=13.2.0'}
+
load-tsconfig@0.2.5:
resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -3650,6 +5060,9 @@ packages:
long@5.3.2:
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
@@ -3660,20 +5073,99 @@ packages:
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
- lru-cache@11.2.6:
- resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==}
+ lru-cache@11.2.7:
+ resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==}
engines: {node: 20 || >=22}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ lru-cache@7.18.3:
+ resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
+ engines: {node: '>=12'}
+
+ lucide-react@0.577.0:
+ resolution: {integrity: sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ magicast@0.5.2:
+ resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==}
+
+ markdown-extensions@2.0.0:
+ resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
+ engines: {node: '>=16'}
+
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-definitions@6.0.0:
+ resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
+
+ mdast-util-directive@3.1.0:
+ resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==}
+
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.3:
+ resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdx@3.0.0:
+ resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
+ mdn-data@2.0.28:
+ resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
+
+ mdn-data@2.27.1:
+ resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
+
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -3681,6 +5173,114 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
+ micromark-core-commonmark@2.0.3:
+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+ micromark-extension-directive@3.0.2:
+ resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==}
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
+
+ micromark-extension-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
+ micromark-extension-gfm-table@2.1.1:
+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
+ micromark-extension-mdx-expression@3.0.1:
+ resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
+
+ micromark-extension-mdx-jsx@3.0.2:
+ resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
+
+ micromark-extension-mdx-md@2.0.0:
+ resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
+
+ micromark-extension-mdxjs@3.0.0:
+ resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
+
+ micromark-factory-destination@2.0.1:
+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+ micromark-factory-label@2.0.1:
+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+ micromark-factory-mdx-expression@2.0.3:
+ resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
+
+ micromark-factory-space@2.0.1:
+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+ micromark-factory-title@2.0.1:
+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+ micromark-factory-whitespace@2.0.1:
+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-chunked@2.0.1:
+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+ micromark-util-classify-character@2.0.1:
+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+ micromark-util-combine-extensions@2.0.1:
+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-events-to-acorn@2.0.3:
+ resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
+
+ micromark-util-html-tag-name@2.0.1:
+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+ micromark-util-normalize-identifier@2.0.1:
+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+ micromark-util-resolve-all@2.0.1:
+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-subtokenize@2.1.0:
+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ micromark@4.0.2:
+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -3740,9 +5340,20 @@ packages:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
+ mrmime@2.0.1:
+ resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
+ engines: {node: '>=10'}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ muggle-string@0.4.1:
+ resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+
+ mute-stream@1.0.0:
+ resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -3766,6 +5377,14 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
+ neotraverse@0.6.18:
+ resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==}
+ engines: {node: '>= 10'}
+
+ netmask@2.0.2:
+ resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
+ engines: {node: '>= 0.4.0'}
+
next-intl-swc-plugin-extractor@4.8.3:
resolution: {integrity: sha512-YcaT+R9z69XkGhpDarVFWUprrCMbxgIQYPUaXoE6LGVnLjGdo8hu3gL6bramDVjNKViYY8a/pXPy7Bna0mXORg==}
@@ -3779,8 +5398,14 @@ packages:
typescript:
optional: true
- next@16.1.6:
- resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==}
+ next-mdx-remote@6.0.0:
+ resolution: {integrity: sha512-cJEpEZlgD6xGjB4jL8BnI8FaYdN9BzZM4NwadPe1YQr7pqoWjg9EBCMv3nXBkuHqMRfv2y33SzUsuyNh9LFAQQ==}
+ engines: {node: '>=14', npm: '>=7'}
+ peerDependencies:
+ react: '>=16'
+
+ next@16.2.0:
+ resolution: {integrity: sha512-NLBVrJy1pbV1Yn00L5sU4vFyAHt5XuSjzrNyFnxo6Com0M0KrL6hHM5B99dbqXb2bE9pm4Ow3Zl1xp6HVY9edQ==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -3800,6 +5425,9 @@ packages:
sass:
optional: true
+ nlcst-to-string@4.0.0:
+ resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
@@ -3819,6 +5447,12 @@ packages:
encoding:
optional: true
+ node-int64@0.4.0:
+ resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
+
+ node-mock-http@1.0.4:
+ resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}
+
node-releases@2.0.36:
resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==}
@@ -3826,6 +5460,9 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
+ nth-check@2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+
nypm@0.6.5:
resolution: {integrity: sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==}
engines: {node: '>=18'}
@@ -3866,6 +5503,12 @@ packages:
obliterator@2.0.5:
resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==}
+ obug@2.1.1:
+ resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+
+ ofetch@1.5.1:
+ resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==}
+
ohash@2.0.11:
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
@@ -3880,6 +5523,24 @@ packages:
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
+ oniguruma-parser@0.12.1:
+ resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
+
+ oniguruma-to-es@4.3.5:
+ resolution: {integrity: sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==}
+
+ openai@6.32.0:
+ resolution: {integrity: sha512-j3k+BjydAf8yQlcOI7WUQMQTbbF5GEIMAE2iZYCOzwwB3S2pCheaWYp+XZRNAch4jWVc52PMDGRRjutao3lLCg==}
+ hasBin: true
+ peerDependencies:
+ ws: ^8.18.0
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ ws:
+ optional: true
+ zod:
+ optional: true
+
openapi-types@12.1.3:
resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
@@ -3909,6 +5570,10 @@ packages:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
+ p-limit@6.2.0:
+ resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==}
+ engines: {node: '>=18'}
+
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -3921,16 +5586,39 @@ packages:
resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
engines: {node: '>=6'}
+ p-queue@8.1.1:
+ resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==}
+ engines: {node: '>=18'}
+
+ p-timeout@6.1.4:
+ resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==}
+ engines: {node: '>=14.16'}
+
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
+ pac-proxy-agent@7.2.0:
+ resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==}
+ engines: {node: '>= 14'}
+
+ pac-resolver@7.0.1:
+ resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==}
+ engines: {node: '>= 14'}
+
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-manager-detector@0.2.11:
resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
+ package-manager-detector@1.6.0:
+ resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
+
+ pagefind@1.4.0:
+ resolution: {integrity: sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==}
+ hasBin: true
+
pako@0.2.9:
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
@@ -3938,6 +5626,18 @@ packages:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
+ parse-latin@7.0.0:
+ resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
+
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -3957,6 +5657,9 @@ packages:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22}
+ path-to-regexp@8.3.0:
+ resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
+
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -3971,8 +5674,11 @@ packages:
resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
engines: {node: '>= 14.16'}
- pdfkit@0.17.2:
- resolution: {integrity: sha512-UnwF5fXy08f0dnp4jchFYAROKMNTaPqb/xgR8GtCzIcqoTnbOqtp3bwKvO4688oHI6vzEEs8Q6vqqEnC5IUELw==}
+ pdfkit@0.18.0:
+ resolution: {integrity: sha512-NvUwSDZ0eYEzqAiWwVQkRkjYUkZ48kcsHuCO31ykqPPIVkwoSDjDGiwIgHHNtsiwls3z3P/zy4q00hl2chg2Ug==}
+
+ pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
@@ -3988,6 +5694,9 @@ packages:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
+ piccolore@0.1.3:
+ resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -4072,6 +5781,16 @@ packages:
yaml:
optional: true
+ postcss-nested@6.2.0:
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+
postcss@8.4.31:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -4096,8 +5815,8 @@ packages:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
- posthog-js@1.360.1:
- resolution: {integrity: sha512-wtKZm0b0SLYLtk0T3SiyXn9cBhwE421fPcJUJ7cRpJmsysHKJcOJ9O/Q7nx7aDj6LvTFILuzjzYO3YTCjbWgqQ==}
+ posthog-js@1.362.0:
+ resolution: {integrity: sha512-qPHkAk9G19xVDAQLoQ1FOLNE9BBq+FDePhkOevbdUQcFJVNHVc+j7E/ndQ+olGnDuiSMdgAb5c6yGk7PD9Z0ug==}
preact@10.29.0:
resolution: {integrity: sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg==}
@@ -4126,6 +5845,10 @@ packages:
typescript:
optional: true
+ prismjs@1.30.0:
+ resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
+ engines: {node: '>=6'}
+
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
@@ -4143,14 +5866,25 @@ packages:
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
engines: {node: '>=0.4.0'}
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
protobufjs@7.5.4:
resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
engines: {node: '>=12.0.0'}
- proxy-from-env@1.1.0:
+ proxy-agent@6.5.0:
+ resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==}
+ engines: {node: '>= 14'}
+
+ proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
pump@3.0.4:
@@ -4180,21 +5914,46 @@ packages:
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+ radix3@1.1.2:
+ resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
+
rc9@2.1.2:
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
- react-dom@19.2.3:
- resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
+ react-dom@19.2.4:
+ resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
peerDependencies:
- react: ^19.2.3
+ react: ^19.2.4
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
- react@19.2.3:
- resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
+ react-markdown@10.1.0:
+ resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
+ peerDependencies:
+ '@types/react': '>=18'
+ react: '>=18'
+
+ react-redux@9.2.0:
+ resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==}
+ peerDependencies:
+ '@types/react': ^18.2.25 || ^19
+ react: ^18.0 || ^19
+ redux: ^5.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ redux:
+ optional: true
+
+ react@19.2.4:
+ resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
+ read-excel-file@7.0.2:
+ resolution: {integrity: sha512-EfEmV3MwKspbRSBtLPS5UMz64YC+4oNjATrKZFGGZQD7MaU7NgO2UWN942o4oPg0F56pKECSvP48nY+Wmiofug==}
+ engines: {node: '>=18'}
+
read-yaml-file@1.1.0:
resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
engines: {node: '>=6'}
@@ -4213,18 +5972,116 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
+ readdirp@5.0.0:
+ resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
+ engines: {node: '>= 20.19.0'}
+
+ reading-time@1.5.0:
+ resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==}
+
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
+ recharts@3.8.0:
+ resolution: {integrity: sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ recma-build-jsx@1.0.0:
+ resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
+
+ recma-jsx@1.0.1:
+ resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ recma-parse@1.0.0:
+ resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
+
+ recma-stringify@1.0.0:
+ resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
+
+ redux-thunk@3.1.0:
+ resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
+ peerDependencies:
+ redux: ^5.0.0
+
+ redux@5.0.1:
+ resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
+
+ reflect-metadata@0.2.2:
+ resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
+
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.1.0:
+ resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
+
regexp.prototype.flags@1.5.4:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
+ rehype-expressive-code@0.41.7:
+ resolution: {integrity: sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ==}
+
+ rehype-format@5.0.1:
+ resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==}
+
+ rehype-parse@9.0.1:
+ resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==}
+
+ rehype-raw@7.0.0:
+ resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
+
+ rehype-recma@1.0.0:
+ resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
+
+ rehype-stringify@10.0.1:
+ resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
+
+ rehype@13.0.2:
+ resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==}
+
+ remark-directive@3.0.1:
+ resolution: {integrity: sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==}
+
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-mdx@3.1.1:
+ resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-smartypants@3.0.2:
+ resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==}
+ engines: {node: '>=16.0.0'}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+
+ request-light@0.5.8:
+ resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==}
+
+ request-light@0.7.0:
+ resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==}
+
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -4240,8 +6097,11 @@ packages:
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
- resend@6.9.3:
- resolution: {integrity: sha512-GRXjH9XZBJA+daH7bBVDuTShr22iWCxXA8P7t495G4dM/RC+d+3gHBK/6bz9K6Vpcq11zRQKmD+B+jECwQlyGQ==}
+ reselect@5.1.1:
+ resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
+
+ resend@6.9.4:
+ resolution: {integrity: sha512-/M3dsJzu5OgozqVsA4Psd/1L7EdePgOIIxClas453GOQYFG3VHc2ZyCHZFlvqsc9aZCCd2BJRRqZgWC8D9c7/g==}
engines: {node: '>=20'}
peerDependencies:
'@react-email/render': '*'
@@ -4281,6 +6141,18 @@ packages:
resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==}
engines: {node: '>=10'}
+ retext-latin@4.0.0:
+ resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}
+
+ retext-smartypants@6.2.0:
+ resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==}
+
+ retext-stringify@4.0.0:
+ resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==}
+
+ retext@9.0.0:
+ resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -4293,9 +6165,16 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ run-async@3.0.0:
+ resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
+ engines: {node: '>=0.12.0'}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ rxjs@7.8.2:
+ resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
+
safe-array-concat@1.1.3:
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
@@ -4314,8 +6193,9 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
- safe-regex2@5.0.0:
- resolution: {integrity: sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==}
+ safe-regex2@5.1.0:
+ resolution: {integrity: sha512-pNHAuBW7TrcleFHsxBr5QMi/Iyp0ENjUKz7GCcX1UO7cMh+NmVK6HxQckNL1tJp1XAJVjG6B8OKIPqodqj9rtw==}
+ hasBin: true
safe-stable-stringify@2.5.0:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
@@ -4324,6 +6204,10 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+ sax@1.6.0:
+ resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==}
+ engines: {node: '>=11.0.0'}
+
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
@@ -4331,6 +6215,10 @@ packages:
resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==}
engines: {node: '>= 10.13.0'}
+ section-matter@1.0.0:
+ resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
+ engines: {node: '>=4'}
+
secure-json-parse@4.1.0:
resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==}
@@ -4364,6 +6252,10 @@ packages:
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+ sharp@0.33.5:
+ resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -4376,6 +6268,13 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
+
+ shiki@3.23.0:
+ resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==}
+
side-channel-list@1.0.0:
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
engines: {node: '>= 0.4'}
@@ -4399,6 +6298,17 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
+ simple-swizzle@0.2.4:
+ resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==}
+
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ sitemap@9.0.1:
+ resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==}
+ engines: {node: '>=20.19.5', npm: '>=10.8.2'}
+ hasBin: true
+
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -4411,6 +6321,22 @@ packages:
resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==}
engines: {node: '>=20'}
+ smart-buffer@4.2.0:
+ resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
+ engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
+
+ smol-toml@1.6.0:
+ resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==}
+ engines: {node: '>= 18'}
+
+ socks-proxy-agent@8.0.5:
+ resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==}
+ engines: {node: '>= 14'}
+
+ socks@2.8.7:
+ resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==}
+ engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
+
sonic-boom@4.2.1:
resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==}
@@ -4429,6 +6355,9 @@ packages:
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
engines: {node: '>= 12'}
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
spawndamnit@3.0.1:
resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
@@ -4439,6 +6368,9 @@ packages:
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+ sprintf-js@1.1.2:
+ resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==}
+
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
@@ -4459,6 +6391,9 @@ packages:
std-env@3.10.0:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+ std-env@4.0.0:
+ resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==}
+
steed@1.1.3:
resolution: {integrity: sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==}
@@ -4466,6 +6401,9 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
+ stream-replace-string@2.0.0:
+ resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}
+
streamx@2.23.0:
resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==}
@@ -4518,6 +6456,9 @@ packages:
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -4526,6 +6467,10 @@ packages:
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
engines: {node: '>=12'}
+ strip-bom-string@1.0.0:
+ resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
+ engines: {node: '>=0.10.0'}
+
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
@@ -4547,6 +6492,16 @@ packages:
'@types/node':
optional: true
+ strtok3@10.3.5:
+ resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==}
+ engines: {node: '>=18'}
+
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'}
@@ -4577,8 +6532,13 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
- svix@1.84.1:
- resolution: {integrity: sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==}
+ svgo@4.0.1:
+ resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==}
+ engines: {node: '>=16'}
+ hasBin: true
+
+ svix@1.86.0:
+ resolution: {integrity: sha512-/HTvXwjLJe1l/MsLXAO1ddCYxElJk4eNR4DzOjDOEmGrPN/3BtBE8perGwMAaJ2sT5T172VkBYzmHcjUfM1JRQ==}
tapable@2.3.0:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
@@ -4610,8 +6570,8 @@ packages:
uglify-js:
optional: true
- terser@5.46.0:
- resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==}
+ terser@5.46.1:
+ resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==}
engines: {node: '>=10'}
hasBin: true
@@ -4632,14 +6592,17 @@ packages:
tiny-inflate@1.0.3:
resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+ tiny-invariant@1.3.3:
+ resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
- tinyexec@1.0.2:
- resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ tinyexec@1.0.4:
+ resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==}
engines: {node: '>=18'}
tinyglobby@0.2.15:
@@ -4654,6 +6617,10 @@ packages:
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
engines: {node: '>=14.0.0'}
+ tinyrainbow@3.1.0:
+ resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
+ engines: {node: '>=14.0.0'}
+
tinyspy@3.0.2:
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
engines: {node: '>=14.0.0'}
@@ -4670,6 +6637,10 @@ packages:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
+ token-types@6.1.2:
+ resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==}
+ engines: {node: '>=14.16'}
+
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
@@ -4677,11 +6648,17 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
ts-algebra@2.0.0:
resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==}
- ts-api-utils@2.4.0:
- resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
+ ts-api-utils@2.5.0:
+ resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
@@ -4689,6 +6666,16 @@ packages:
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ tsconfck@3.1.6:
+ resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
@@ -4719,48 +6706,26 @@ packages:
engines: {node: '>=18.0.0'}
hasBin: true
- turbo-darwin-64@2.8.14:
- resolution: {integrity: sha512-9sFi7n2lLfEsGWi5OEoA/eTtQU2BPKtzSYKqufMtDeRmqMT9vKjbv9gJCRkllSVE9BOXA0qXC3diyX8V8rKIKw==}
- cpu: [x64]
- os: [darwin]
-
- turbo-darwin-arm64@2.8.14:
- resolution: {integrity: sha512-aS4yJuy6A1PCLws+PJpZP0qCURG8Y5iVx13z/WAbKyeDTY6W6PiGgcEllSaeLGxyn++382ztN/EZH85n2zZ6VQ==}
- cpu: [arm64]
- os: [darwin]
-
- turbo-linux-64@2.8.14:
- resolution: {integrity: sha512-XC6wPUDJkakjhNLaS0NrHDMiujRVjH+naEAwvKLArgqRaFkNxjmyNDRM4eu3soMMFmjym6NTxYaF74rvET+Orw==}
- cpu: [x64]
- os: [linux]
-
- turbo-linux-arm64@2.8.14:
- resolution: {integrity: sha512-ChfE7isyVNjZrVSPDwcfqcHLG/FuIBbOFxnt1FM8vSuBGzHAs8AlTdwFNIxlEMJfZ8Ad9mdMxdmsCUPIWiQ6cg==}
- cpu: [arm64]
- os: [linux]
-
- turbo-windows-64@2.8.14:
- resolution: {integrity: sha512-FTbIeQL1ycLFW2t9uQNMy+bRSzi3Xhwun/e7ZhFBdM+U0VZxxrtfYEBM9CHOejlfqomk6Jh7aRz0sJoqYn39Hg==}
- cpu: [x64]
- os: [win32]
-
- turbo-windows-arm64@2.8.14:
- resolution: {integrity: sha512-KgZX12cTyhY030qS7ieT8zRkhZZE2VWJasDFVUSVVn17nR7IShpv68/7j5UqJNeRLIGF1XPK0phsP5V5yw3how==}
- cpu: [arm64]
- os: [win32]
-
- turbo@2.8.14:
- resolution: {integrity: sha512-UCTxeMNYT1cKaHiIFdLCQ7ulI+jw5i5uOnJOrRXsgUD7G3+OjlUjwVd7JfeVt2McWSVGjYA3EVW/v1FSsJ5DtA==}
+ turbo@2.8.20:
+ resolution: {integrity: sha512-Rb4qk5YT8RUwwdXtkLpkVhNEe/lor6+WV7S5tTlLpxSz6MjV5Qi8jGNn4gS6NAvrYGA/rNrE6YUQM85sCZUDbQ==}
hasBin: true
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
+ type-fest@0.21.3:
+ resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+ engines: {node: '>=10'}
+
type-fest@0.7.1:
resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==}
engines: {node: '>=8'}
+ type-fest@4.41.0:
+ resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
+ engines: {node: '>=16'}
+
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -4777,8 +6742,14 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
- typescript-eslint@8.56.1:
- resolution: {integrity: sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==}
+ typesafe-path@0.2.2:
+ resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==}
+
+ typescript-auto-import-cache@0.3.6:
+ resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==}
+
+ typescript-eslint@8.57.2:
+ resolution: {integrity: sha512-VEPQ0iPgWO/sBaZOU1xo4nuNdODVOajPnTIbog2GKYr31nIlZ0fWPoCQgGfF3ETyBl1vn63F/p50Um9Z4J8O8A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
@@ -4792,26 +6763,154 @@ packages:
ufo@1.6.3:
resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
+ uid@2.0.2:
+ resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==}
+ engines: {node: '>=8'}
+
+ uint8array-extras@1.5.0:
+ resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==}
+ engines: {node: '>=18'}
+
+ ultrahtml@1.6.0:
+ resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==}
+
unbox-primitive@1.1.0:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
+ uncrypto@0.1.3:
+ resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
+
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ undici-types@7.16.0:
+ resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
unicode-properties@1.4.1:
resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
unicode-trie@2.0.0:
resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unifont@0.7.4:
+ resolution: {integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==}
+
+ unist-util-find-after@5.0.0:
+ resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-modify-children@4.0.0:
+ resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==}
+
+ unist-util-position-from-estree@2.0.0:
+ resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-remove-position@5.0.0:
+ resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}
+
+ unist-util-remove@4.0.0:
+ resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-children@3.0.0:
+ resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.1.0:
+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
+
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
unrs-resolver@1.11.1:
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
+ unstorage@1.17.4:
+ resolution: {integrity: sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==}
+ peerDependencies:
+ '@azure/app-configuration': ^1.8.0
+ '@azure/cosmos': ^4.2.0
+ '@azure/data-tables': ^13.3.0
+ '@azure/identity': ^4.6.0
+ '@azure/keyvault-secrets': ^4.9.0
+ '@azure/storage-blob': ^12.26.0
+ '@capacitor/preferences': ^6 || ^7 || ^8
+ '@deno/kv': '>=0.9.0'
+ '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0
+ '@planetscale/database': ^1.19.0
+ '@upstash/redis': ^1.34.3
+ '@vercel/blob': '>=0.27.1'
+ '@vercel/functions': ^2.2.12 || ^3.0.0
+ '@vercel/kv': ^1 || ^2 || ^3
+ aws4fetch: ^1.0.20
+ db0: '>=0.2.1'
+ idb-keyval: ^6.2.1
+ ioredis: ^5.4.2
+ uploadthing: ^7.4.4
+ peerDependenciesMeta:
+ '@azure/app-configuration':
+ optional: true
+ '@azure/cosmos':
+ optional: true
+ '@azure/data-tables':
+ optional: true
+ '@azure/identity':
+ optional: true
+ '@azure/keyvault-secrets':
+ optional: true
+ '@azure/storage-blob':
+ optional: true
+ '@capacitor/preferences':
+ optional: true
+ '@deno/kv':
+ optional: true
+ '@netlify/blobs':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@upstash/redis':
+ optional: true
+ '@vercel/blob':
+ optional: true
+ '@vercel/functions':
+ optional: true
+ '@vercel/kv':
+ optional: true
+ aws4fetch:
+ optional: true
+ db0:
+ optional: true
+ idb-keyval:
+ optional: true
+ ioredis:
+ optional: true
+ uploadthing:
+ optional: true
+
+ unzipper@0.12.3:
+ resolution: {integrity: sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA==}
+
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
@@ -4826,6 +6925,11 @@ packages:
peerDependencies:
react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+ use-sync-external-store@1.6.0:
+ resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
@@ -4837,6 +6941,21 @@ packages:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
hasBin: true
+ vfile-location@5.0.3:
+ resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
+
+ vfile-matter@5.0.1:
+ resolution: {integrity: sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw==}
+
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
+ victory-vendor@37.3.6:
+ resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==}
+
vite-node@2.1.9:
resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -4873,6 +6992,54 @@ packages:
terser:
optional: true
+ vite@6.4.1:
+ resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitefu@1.1.2:
+ resolution: {integrity: sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
vitest@2.1.9:
resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -4898,39 +7065,172 @@ packages:
jsdom:
optional: true
- watchpack@2.5.1:
- resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==}
- engines: {node: '>=10.13.0'}
-
- web-vitals@5.1.0:
- resolution: {integrity: sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==}
-
- webidl-conversions@3.0.1:
- resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
-
- webpack-sources@3.3.4:
- resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==}
- engines: {node: '>=10.13.0'}
-
- webpack@5.105.4:
- resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==}
- engines: {node: '>=10.13.0'}
+ vitest@4.1.0:
+ resolution: {integrity: sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==}
+ engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
hasBin: true
peerDependencies:
- webpack-cli: '*'
+ '@edge-runtime/vm': '*'
+ '@opentelemetry/api': ^1.9.0
+ '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+ '@vitest/browser-playwright': 4.1.0
+ '@vitest/browser-preview': 4.1.0
+ '@vitest/browser-webdriverio': 4.1.0
+ '@vitest/ui': 4.1.0
+ happy-dom: '*'
+ jsdom: '*'
+ vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0
peerDependenciesMeta:
- webpack-cli:
+ '@edge-runtime/vm':
optional: true
-
- whatwg-url@5.0.0:
- resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
-
- which-boxed-primitive@1.1.1:
- resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
- engines: {node: '>= 0.4'}
-
- which-builtin-type@1.2.1:
- resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+ '@opentelemetry/api':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser-playwright':
+ optional: true
+ '@vitest/browser-preview':
+ optional: true
+ '@vitest/browser-webdriverio':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ volar-service-css@0.0.70:
+ resolution: {integrity: sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-emmet@0.0.70:
+ resolution: {integrity: sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-html@0.0.70:
+ resolution: {integrity: sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-prettier@0.0.70:
+ resolution: {integrity: sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ prettier: ^2.2 || ^3.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+ prettier:
+ optional: true
+
+ volar-service-typescript-twoslash-queries@0.0.70:
+ resolution: {integrity: sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-typescript@0.0.70:
+ resolution: {integrity: sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-yaml@0.0.70:
+ resolution: {integrity: sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ vscode-css-languageservice@6.3.10:
+ resolution: {integrity: sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==}
+
+ vscode-html-languageservice@5.6.2:
+ resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==}
+
+ vscode-json-languageservice@4.1.8:
+ resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==}
+ engines: {npm: '>=7.0.0'}
+
+ vscode-jsonrpc@8.2.0:
+ resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
+ engines: {node: '>=14.0.0'}
+
+ vscode-languageserver-protocol@3.17.5:
+ resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
+
+ vscode-languageserver-textdocument@1.0.12:
+ resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}
+
+ vscode-languageserver-types@3.17.5:
+ resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
+
+ vscode-languageserver@9.0.1:
+ resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
+ hasBin: true
+
+ vscode-nls@5.2.0:
+ resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}
+
+ vscode-uri@3.1.0:
+ resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
+ watchpack@2.5.1:
+ resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==}
+ engines: {node: '>=10.13.0'}
+
+ wcwidth@1.0.1:
+ resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
+
+ web-namespaces@2.0.1:
+ resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
+
+ web-vitals@5.1.0:
+ resolution: {integrity: sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==}
+
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ webpack-sources@3.3.4:
+ resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==}
+ engines: {node: '>=10.13.0'}
+
+ webpack@5.105.4:
+ resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ peerDependencies:
+ webpack-cli: '*'
+ peerDependenciesMeta:
+ webpack-cli:
+ optional: true
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+ which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+
+ which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
engines: {node: '>= 0.4'}
which-collection@1.0.2:
@@ -4940,6 +7240,10 @@ packages:
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+ which-pm-runs@1.1.0:
+ resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==}
+ engines: {node: '>=4'}
+
which-typed-array@1.1.20:
resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
engines: {node: '>= 0.4'}
@@ -4954,6 +7258,10 @@ packages:
engines: {node: '>=8'}
hasBin: true
+ widest-line@5.0.0:
+ resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==}
+ engines: {node: '>=18'}
+
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
@@ -4993,12 +7301,28 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
+ xxhash-wasm@1.1.0:
+ resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
+
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yaml-language-server@1.20.0:
+ resolution: {integrity: sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==}
+ hasBin: true
+
+ yaml@2.7.1:
+ resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
+ engines: {node: '>= 14'}
+ hasBin: true
+
yaml@2.8.2:
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
engines: {node: '>= 14.6'}
@@ -5008,23 +7332,58 @@ packages:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
+ yauzl@3.2.1:
+ resolution: {integrity: sha512-k1isifdbpNSFEHFJ1ZY4YDewv0IH9FR61lDetaRMD3j2ae3bIXGV+7c+LHCqtQGofSd8PIyV4X6+dHMAnSr60A==}
+ engines: {node: '>=12'}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ yocto-queue@1.2.2:
+ resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
+ engines: {node: '>=12.20'}
+
+ yocto-spinner@0.2.3:
+ resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==}
+ engines: {node: '>=18.19'}
+
+ yoctocolors@2.1.2:
+ resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
+ engines: {node: '>=18'}
+
zip-stream@6.0.1:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
- zod-openapi@4.2.4:
- resolution: {integrity: sha512-tsrQpbpqFCXqVXUzi3TPwFhuMtLN3oNZobOtYnK6/5VkXsNdnIgyNr4r8no4wmYluaxzN3F7iS+8xCW8BmMQ8g==}
- engines: {node: '>=18'}
+ zod-openapi@5.4.6:
+ resolution: {integrity: sha512-P2jsOOBAq/6hCwUsMCjUATZ8szkMsV5VAwZENfyxp2Hc/XPJQpVwAgevWZc65xZauCwWB9LAn7zYeiCJFAEL+A==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ zod: ^3.25.74 || ^4.0.0
+
+ zod-to-json-schema@3.25.1:
+ resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==}
+ peerDependencies:
+ zod: ^3.25 || ^4
+
+ zod-to-ts@1.2.0:
+ resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==}
peerDependencies:
- zod: ^3.21.4
+ typescript: ^4.9.4 || ^5.0.2
+ zod: ^3
zod-validation-error@4.0.2:
resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
@@ -5035,13 +7394,161 @@ packages:
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+ zod@4.3.6:
+ resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
+
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
snapshots:
- '@anthropic-ai/sdk@0.78.0(zod@3.25.76)':
+ '@anthropic-ai/sdk@0.80.0(zod@4.3.6)':
dependencies:
json-schema-to-ts: 3.1.1
optionalDependencies:
- zod: 3.25.76
+ zod: 4.3.6
+
+ '@astrojs/check@0.9.8(prettier@3.8.1)(typescript@5.9.3)':
+ dependencies:
+ '@astrojs/language-server': 2.16.6(prettier@3.8.1)(typescript@5.9.3)
+ chokidar: 4.0.3
+ kleur: 4.1.5
+ typescript: 5.9.3
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - prettier
+ - prettier-plugin-astro
+
+ '@astrojs/compiler@2.13.1': {}
+
+ '@astrojs/internal-helpers@0.7.6': {}
+
+ '@astrojs/language-server@2.16.6(prettier@3.8.1)(typescript@5.9.3)':
+ dependencies:
+ '@astrojs/compiler': 2.13.1
+ '@astrojs/yaml2ts': 0.2.3
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@volar/kit': 2.4.28(typescript@5.9.3)
+ '@volar/language-core': 2.4.28
+ '@volar/language-server': 2.4.28
+ '@volar/language-service': 2.4.28
+ muggle-string: 0.4.1
+ tinyglobby: 0.2.15
+ volar-service-css: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-emmet: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-html: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-prettier: 0.0.70(@volar/language-service@2.4.28)(prettier@3.8.1)
+ volar-service-typescript: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-typescript-twoslash-queries: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-yaml: 0.0.70(@volar/language-service@2.4.28)
+ vscode-html-languageservice: 5.6.2
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ prettier: 3.8.1
+ transitivePeerDependencies:
+ - typescript
+
+ '@astrojs/markdown-remark@6.3.11':
+ dependencies:
+ '@astrojs/internal-helpers': 0.7.6
+ '@astrojs/prism': 3.3.0
+ github-slugger: 2.0.0
+ hast-util-from-html: 2.0.3
+ hast-util-to-text: 4.0.2
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ mdast-util-definitions: 6.0.0
+ rehype-raw: 7.0.0
+ rehype-stringify: 10.0.1
+ remark-gfm: 4.0.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ remark-smartypants: 3.0.2
+ shiki: 3.23.0
+ smol-toml: 1.6.0
+ unified: 11.0.5
+ unist-util-remove-position: 5.0.0
+ unist-util-visit: 5.1.0
+ unist-util-visit-parents: 6.0.2
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/mdx@4.3.14(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))':
+ dependencies:
+ '@astrojs/markdown-remark': 6.3.11
+ '@mdx-js/mdx': 3.1.1
+ acorn: 8.16.0
+ astro: 5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ es-module-lexer: 1.7.0
+ estree-util-visit: 2.0.0
+ hast-util-to-html: 9.0.5
+ piccolore: 0.1.3
+ rehype-raw: 7.0.0
+ remark-gfm: 4.0.1
+ remark-smartypants: 3.0.2
+ source-map: 0.7.6
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/prism@3.3.0':
+ dependencies:
+ prismjs: 1.30.0
+
+ '@astrojs/sitemap@3.7.1':
+ dependencies:
+ sitemap: 9.0.1
+ stream-replace-string: 2.0.0
+ zod: 4.3.6
+
+ '@astrojs/starlight@0.33.2(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))':
+ dependencies:
+ '@astrojs/mdx': 4.3.14(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
+ '@astrojs/sitemap': 3.7.1
+ '@pagefind/default-ui': 1.4.0
+ '@types/hast': 3.0.4
+ '@types/js-yaml': 4.0.9
+ '@types/mdast': 4.0.4
+ astro: 5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ astro-expressive-code: 0.41.7(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))
+ bcp-47: 2.1.0
+ hast-util-from-html: 2.0.3
+ hast-util-select: 6.0.4
+ hast-util-to-string: 3.0.1
+ hastscript: 9.0.1
+ i18next: 23.16.8
+ js-yaml: 4.1.1
+ klona: 2.0.6
+ mdast-util-directive: 3.1.0
+ mdast-util-to-markdown: 2.1.2
+ mdast-util-to-string: 4.0.0
+ pagefind: 1.4.0
+ rehype: 13.0.2
+ rehype-format: 5.0.1
+ remark-directive: 3.0.1
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/telemetry@3.3.0':
+ dependencies:
+ ci-info: 4.4.0
+ debug: 4.4.3
+ dlv: 1.1.3
+ dset: 3.1.4
+ is-docker: 3.0.0
+ is-wsl: 3.1.1
+ which-pm-runs: 1.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/yaml2ts@0.2.3':
+ dependencies:
+ yaml: 2.8.2
'@babel/code-frame@7.29.0':
dependencies:
@@ -5057,8 +7564,8 @@ snapshots:
'@babel/generator': 7.29.1
'@babel/helper-compilation-targets': 7.28.6
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
- '@babel/helpers': 7.28.6
- '@babel/parser': 7.29.0
+ '@babel/helpers': 7.29.2
+ '@babel/parser': 7.29.2
'@babel/template': 7.28.6
'@babel/traverse': 7.29.0
'@babel/types': 7.29.0
@@ -5073,7 +7580,7 @@ snapshots:
'@babel/generator@7.29.1':
dependencies:
- '@babel/parser': 7.29.0
+ '@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
@@ -5111,21 +7618,23 @@ snapshots:
'@babel/helper-validator-option@7.27.1': {}
- '@babel/helpers@7.28.6':
+ '@babel/helpers@7.29.2':
dependencies:
'@babel/template': 7.28.6
'@babel/types': 7.29.0
- '@babel/parser@7.29.0':
+ '@babel/parser@7.29.2':
dependencies:
'@babel/types': 7.29.0
'@babel/runtime@7.28.6': {}
+ '@babel/runtime@7.29.2': {}
+
'@babel/template@7.28.6':
dependencies:
'@babel/code-frame': 7.29.0
- '@babel/parser': 7.29.0
+ '@babel/parser': 7.29.2
'@babel/types': 7.29.0
'@babel/traverse@7.29.0':
@@ -5133,7 +7642,7 @@ snapshots:
'@babel/code-frame': 7.29.0
'@babel/generator': 7.29.1
'@babel/helper-globals': 7.28.0
- '@babel/parser': 7.29.0
+ '@babel/parser': 7.29.2
'@babel/template': 7.28.6
'@babel/types': 7.29.0
debug: 4.4.3
@@ -5145,6 +7654,12 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
+ '@borewit/text-codec@0.2.2': {}
+
+ '@capsizecss/unpack@4.0.0':
+ dependencies:
+ fontkitten: 1.0.3
+
'@changesets/apply-release-plan@7.1.0':
dependencies:
'@changesets/config': 3.1.3
@@ -5182,7 +7697,7 @@ snapshots:
transitivePeerDependencies:
- encoding
- '@changesets/cli@2.30.0(@types/node@20.19.37)':
+ '@changesets/cli@2.30.0(@types/node@25.5.0)':
dependencies:
'@changesets/apply-release-plan': 7.1.0
'@changesets/assemble-release-plan': 6.0.9
@@ -5198,7 +7713,7 @@ snapshots:
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@changesets/write': 0.4.0
- '@inquirer/external-editor': 1.0.3(@types/node@20.19.37)
+ '@inquirer/external-editor': 1.0.3(@types/node@25.5.0)
'@manypkg/get-packages': 1.1.3
ansi-colors: 4.1.3
enquirer: 2.4.1
@@ -5303,18 +7818,43 @@ snapshots:
human-id: 4.1.3
prettier: 2.8.8
- '@emnapi/core@1.8.1':
+ '@ctrl/tinycolor@4.2.0': {}
+
+ '@emmetio/abbreviation@2.3.3':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/css-abbreviation@2.1.8':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/css-parser@0.4.1':
+ dependencies:
+ '@emmetio/stream-reader': 2.2.0
+ '@emmetio/stream-reader-utils': 0.1.0
+
+ '@emmetio/html-matcher@1.3.0':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/scanner@1.0.4': {}
+
+ '@emmetio/stream-reader-utils@0.1.0': {}
+
+ '@emmetio/stream-reader@2.2.0': {}
+
+ '@emnapi/core@1.9.1':
dependencies:
- '@emnapi/wasi-threads': 1.1.0
+ '@emnapi/wasi-threads': 1.2.0
tslib: 2.8.1
optional: true
- '@emnapi/runtime@1.8.1':
+ '@emnapi/runtime@1.9.1':
dependencies:
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.1.0':
+ '@emnapi/wasi-threads@1.2.0':
dependencies:
tslib: 2.8.1
optional: true
@@ -5322,147 +7862,225 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
+ '@esbuild/aix-ppc64@0.25.12':
+ optional: true
+
'@esbuild/aix-ppc64@0.27.3':
optional: true
'@esbuild/android-arm64@0.21.5':
optional: true
+ '@esbuild/android-arm64@0.25.12':
+ optional: true
+
'@esbuild/android-arm64@0.27.3':
optional: true
'@esbuild/android-arm@0.21.5':
optional: true
+ '@esbuild/android-arm@0.25.12':
+ optional: true
+
'@esbuild/android-arm@0.27.3':
optional: true
'@esbuild/android-x64@0.21.5':
optional: true
+ '@esbuild/android-x64@0.25.12':
+ optional: true
+
'@esbuild/android-x64@0.27.3':
optional: true
'@esbuild/darwin-arm64@0.21.5':
optional: true
+ '@esbuild/darwin-arm64@0.25.12':
+ optional: true
+
'@esbuild/darwin-arm64@0.27.3':
optional: true
'@esbuild/darwin-x64@0.21.5':
optional: true
+ '@esbuild/darwin-x64@0.25.12':
+ optional: true
+
'@esbuild/darwin-x64@0.27.3':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
optional: true
+ '@esbuild/freebsd-arm64@0.25.12':
+ optional: true
+
'@esbuild/freebsd-arm64@0.27.3':
optional: true
'@esbuild/freebsd-x64@0.21.5':
optional: true
+ '@esbuild/freebsd-x64@0.25.12':
+ optional: true
+
'@esbuild/freebsd-x64@0.27.3':
optional: true
'@esbuild/linux-arm64@0.21.5':
optional: true
+ '@esbuild/linux-arm64@0.25.12':
+ optional: true
+
'@esbuild/linux-arm64@0.27.3':
optional: true
'@esbuild/linux-arm@0.21.5':
optional: true
+ '@esbuild/linux-arm@0.25.12':
+ optional: true
+
'@esbuild/linux-arm@0.27.3':
optional: true
'@esbuild/linux-ia32@0.21.5':
optional: true
+ '@esbuild/linux-ia32@0.25.12':
+ optional: true
+
'@esbuild/linux-ia32@0.27.3':
optional: true
'@esbuild/linux-loong64@0.21.5':
optional: true
+ '@esbuild/linux-loong64@0.25.12':
+ optional: true
+
'@esbuild/linux-loong64@0.27.3':
optional: true
'@esbuild/linux-mips64el@0.21.5':
optional: true
+ '@esbuild/linux-mips64el@0.25.12':
+ optional: true
+
'@esbuild/linux-mips64el@0.27.3':
optional: true
'@esbuild/linux-ppc64@0.21.5':
optional: true
+ '@esbuild/linux-ppc64@0.25.12':
+ optional: true
+
'@esbuild/linux-ppc64@0.27.3':
optional: true
'@esbuild/linux-riscv64@0.21.5':
optional: true
+ '@esbuild/linux-riscv64@0.25.12':
+ optional: true
+
'@esbuild/linux-riscv64@0.27.3':
optional: true
'@esbuild/linux-s390x@0.21.5':
optional: true
+ '@esbuild/linux-s390x@0.25.12':
+ optional: true
+
'@esbuild/linux-s390x@0.27.3':
optional: true
'@esbuild/linux-x64@0.21.5':
optional: true
+ '@esbuild/linux-x64@0.25.12':
+ optional: true
+
'@esbuild/linux-x64@0.27.3':
optional: true
+ '@esbuild/netbsd-arm64@0.25.12':
+ optional: true
+
'@esbuild/netbsd-arm64@0.27.3':
optional: true
'@esbuild/netbsd-x64@0.21.5':
optional: true
+ '@esbuild/netbsd-x64@0.25.12':
+ optional: true
+
'@esbuild/netbsd-x64@0.27.3':
optional: true
+ '@esbuild/openbsd-arm64@0.25.12':
+ optional: true
+
'@esbuild/openbsd-arm64@0.27.3':
optional: true
'@esbuild/openbsd-x64@0.21.5':
optional: true
+ '@esbuild/openbsd-x64@0.25.12':
+ optional: true
+
'@esbuild/openbsd-x64@0.27.3':
optional: true
+ '@esbuild/openharmony-arm64@0.25.12':
+ optional: true
+
'@esbuild/openharmony-arm64@0.27.3':
optional: true
'@esbuild/sunos-x64@0.21.5':
optional: true
+ '@esbuild/sunos-x64@0.25.12':
+ optional: true
+
'@esbuild/sunos-x64@0.27.3':
optional: true
'@esbuild/win32-arm64@0.21.5':
optional: true
+ '@esbuild/win32-arm64@0.25.12':
+ optional: true
+
'@esbuild/win32-arm64@0.27.3':
optional: true
'@esbuild/win32-ia32@0.21.5':
optional: true
+ '@esbuild/win32-ia32@0.25.12':
+ optional: true
+
'@esbuild/win32-ia32@0.27.3':
optional: true
'@esbuild/win32-x64@0.21.5':
optional: true
+ '@esbuild/win32-x64@0.25.12':
+ optional: true
+
'@esbuild/win32-x64@0.27.3':
optional: true
@@ -5512,6 +8130,31 @@ snapshots:
'@eslint/core': 0.17.0
levn: 0.4.1
+ '@expressive-code/core@0.41.7':
+ dependencies:
+ '@ctrl/tinycolor': 4.2.0
+ hast-util-select: 6.0.4
+ hast-util-to-html: 9.0.5
+ hast-util-to-text: 4.0.2
+ hastscript: 9.0.1
+ postcss: 8.5.8
+ postcss-nested: 6.2.0(postcss@8.5.8)
+ unist-util-visit: 5.1.0
+ unist-util-visit-parents: 6.0.2
+
+ '@expressive-code/plugin-frames@0.41.7':
+ dependencies:
+ '@expressive-code/core': 0.41.7
+
+ '@expressive-code/plugin-shiki@0.41.7':
+ dependencies:
+ '@expressive-code/core': 0.41.7
+ shiki: 3.23.0
+
+ '@expressive-code/plugin-text-markers@0.41.7':
+ dependencies:
+ '@expressive-code/core': 0.41.7
+
'@fastify/accept-negotiator@2.0.1': {}
'@fastify/ajv-compiler@4.0.5':
@@ -5522,10 +8165,15 @@ snapshots:
'@fastify/busboy@3.2.0': {}
- '@fastify/cors@10.1.0':
+ '@fastify/cookie@11.0.2':
dependencies:
+ cookie: 1.1.1
fastify-plugin: 5.1.0
- mnemonist: 0.40.0
+
+ '@fastify/cors@11.2.0':
+ dependencies:
+ fastify-plugin: 5.1.0
+ toad-cache: 3.7.0
'@fastify/deepmerge@3.2.1': {}
@@ -5557,11 +8205,11 @@ snapshots:
fastify-plugin: 5.1.0
secure-json-parse: 4.1.0
- '@fastify/otel@0.16.0(@opentelemetry/api@1.9.0)':
+ '@fastify/otel@0.17.1(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.208.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.212.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
minimatch: 10.2.4
transitivePeerDependencies:
@@ -5654,25 +8302,47 @@ snapshots:
'@img/colour@1.1.0':
optional: true
+ '@img/sharp-darwin-arm64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-arm64': 1.0.4
+ optional: true
+
'@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
+ '@img/sharp-darwin-x64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.0.4
+ optional: true
+
'@img/sharp-darwin-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.2.4
optional: true
+ '@img/sharp-libvips-darwin-arm64@1.0.4':
+ optional: true
+
'@img/sharp-libvips-darwin-arm64@1.2.4':
optional: true
- '@img/sharp-libvips-darwin-x64@1.2.4':
+ '@img/sharp-libvips-darwin-x64@1.0.4':
+ optional: true
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm64@1.0.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-arm@1.0.5':
+ optional: true
+
'@img/sharp-libvips-linux-arm@1.2.4':
optional: true
@@ -5682,23 +8352,45 @@ snapshots:
'@img/sharp-libvips-linux-riscv64@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-s390x@1.0.4':
+ optional: true
+
'@img/sharp-libvips-linux-s390x@1.2.4':
optional: true
+ '@img/sharp-libvips-linux-x64@1.0.4':
+ optional: true
+
'@img/sharp-libvips-linux-x64@1.2.4':
optional: true
+ '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
+ optional: true
+
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
+ '@img/sharp-libvips-linuxmusl-x64@1.0.4':
+ optional: true
+
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
+ '@img/sharp-linux-arm64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.0.4
+ optional: true
+
'@img/sharp-linux-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
+ '@img/sharp-linux-arm@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.0.5
+ optional: true
+
'@img/sharp-linux-arm@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.2.4
@@ -5714,46 +8406,106 @@ snapshots:
'@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
+ '@img/sharp-linux-s390x@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.0.4
+ optional: true
+
'@img/sharp-linux-s390x@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
+ '@img/sharp-linux-x64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.0.4
+ optional: true
+
'@img/sharp-linux-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.2.4
optional: true
+ '@img/sharp-linuxmusl-arm64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
+ optional: true
+
'@img/sharp-linuxmusl-arm64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
+ '@img/sharp-linuxmusl-x64@0.33.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.0.4
+ optional: true
+
'@img/sharp-linuxmusl-x64@0.34.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
+ '@img/sharp-wasm32@0.33.5':
+ dependencies:
+ '@emnapi/runtime': 1.9.1
+ optional: true
+
'@img/sharp-wasm32@0.34.5':
dependencies:
- '@emnapi/runtime': 1.8.1
+ '@emnapi/runtime': 1.9.1
optional: true
'@img/sharp-win32-arm64@0.34.5':
optional: true
+ '@img/sharp-win32-ia32@0.33.5':
+ optional: true
+
'@img/sharp-win32-ia32@0.34.5':
optional: true
+ '@img/sharp-win32-x64@0.33.5':
+ optional: true
+
'@img/sharp-win32-x64@0.34.5':
optional: true
- '@inquirer/external-editor@1.0.3(@types/node@20.19.37)':
+ '@inquirer/core@6.0.0':
+ dependencies:
+ '@inquirer/type': 1.5.5
+ '@types/mute-stream': 0.0.4
+ '@types/node': 20.19.37
+ '@types/wrap-ansi': 3.0.0
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ cli-spinners: 2.9.2
+ cli-width: 4.1.0
+ figures: 3.2.0
+ mute-stream: 1.0.0
+ run-async: 3.0.0
+ signal-exit: 4.1.0
+ strip-ansi: 6.0.1
+ wrap-ansi: 6.2.0
+
+ '@inquirer/external-editor@1.0.3(@types/node@25.5.0)':
dependencies:
chardet: 2.1.1
iconv-lite: 0.7.2
optionalDependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+
+ '@inquirer/select@1.3.3':
+ dependencies:
+ '@inquirer/core': 6.0.0
+ '@inquirer/type': 1.5.5
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ figures: 3.2.0
+
+ '@inquirer/type@1.5.5':
+ dependencies:
+ mute-stream: 1.0.0
'@isaacs/cliui@8.0.2':
dependencies:
@@ -5788,11 +8540,13 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
+ '@lukeed/csprng@1.1.0': {}
+
'@lukeed/ms@2.0.2': {}
'@manypkg/find-root@1.1.0':
dependencies:
- '@babel/runtime': 7.28.6
+ '@babel/runtime': 7.29.2
'@types/node': 12.20.55
find-up: 4.1.0
fs-extra: 8.1.0
@@ -5806,43 +8560,113 @@ snapshots:
globby: 11.1.0
read-yaml-file: 1.1.0
+ '@mdx-js/mdx@3.1.1':
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdx': 2.0.13
+ acorn: 8.16.0
+ collapse-white-space: 2.1.0
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-util-scope: 1.0.0
+ estree-walker: 3.0.3
+ hast-util-to-jsx-runtime: 2.3.6
+ markdown-extensions: 2.0.0
+ recma-build-jsx: 1.0.0
+ recma-jsx: 1.0.1(acorn@8.16.0)
+ recma-stringify: 1.0.0
+ rehype-recma: 1.0.0
+ remark-mdx: 3.1.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ source-map: 0.7.6
+ unified: 11.0.5
+ unist-util-position-from-estree: 2.0.0
+ unist-util-stringify-position: 4.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.4)':
+ dependencies:
+ '@types/mdx': 2.0.13
+ '@types/react': 19.2.14
+ react: 19.2.4
+
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
- '@emnapi/core': 1.8.1
- '@emnapi/runtime': 1.8.1
+ '@emnapi/core': 1.9.1
+ '@emnapi/runtime': 1.9.1
'@tybys/wasm-util': 0.10.1
optional: true
- '@next/env@16.1.6': {}
+ '@nestjs/axios@4.0.1(@nestjs/common@11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.6)(rxjs@7.8.2)':
+ dependencies:
+ '@nestjs/common': 11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2)
+ axios: 1.13.6
+ rxjs: 7.8.2
+
+ '@nestjs/common@11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2)':
+ dependencies:
+ file-type: 21.3.0
+ iterare: 1.2.1
+ load-esm: 1.0.3
+ reflect-metadata: 0.2.2
+ rxjs: 7.8.2
+ tslib: 2.8.1
+ uid: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@nestjs/core@11.1.16(@nestjs/common@11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)':
+ dependencies:
+ '@nestjs/common': 11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2)
+ '@nuxt/opencollective': 0.4.1
+ fast-safe-stringify: 2.1.1
+ iterare: 1.2.1
+ path-to-regexp: 8.3.0
+ reflect-metadata: 0.2.2
+ rxjs: 7.8.2
+ tslib: 2.8.1
+ uid: 2.0.2
+
+ '@next/env@16.2.0': {}
- '@next/eslint-plugin-next@16.1.6':
+ '@next/eslint-plugin-next@16.2.0':
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@16.1.6':
+ '@next/swc-darwin-arm64@16.2.0':
optional: true
- '@next/swc-darwin-x64@16.1.6':
+ '@next/swc-darwin-x64@16.2.0':
optional: true
- '@next/swc-linux-arm64-gnu@16.1.6':
+ '@next/swc-linux-arm64-gnu@16.2.0':
optional: true
- '@next/swc-linux-arm64-musl@16.1.6':
+ '@next/swc-linux-arm64-musl@16.2.0':
optional: true
- '@next/swc-linux-x64-gnu@16.1.6':
+ '@next/swc-linux-x64-gnu@16.2.0':
optional: true
- '@next/swc-linux-x64-musl@16.1.6':
+ '@next/swc-linux-x64-musl@16.2.0':
optional: true
- '@next/swc-win32-arm64-msvc@16.1.6':
+ '@next/swc-win32-arm64-msvc@16.2.0':
optional: true
- '@next/swc-win32-x64-msvc@16.1.6':
+ '@next/swc-win32-x64-msvc@16.2.0':
optional: true
+ '@noble/ciphers@1.3.0': {}
+
+ '@noble/hashes@1.8.0': {}
+
'@noble/hashes@2.0.1': {}
'@nodelib/fs.scandir@2.1.5':
@@ -5859,6 +8683,47 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {}
+ '@nuxt/opencollective@0.4.1':
+ dependencies:
+ consola: 3.4.2
+
+ '@nuxtjs/opencollective@0.3.2':
+ dependencies:
+ chalk: 4.1.2
+ consola: 2.15.3
+ node-fetch: 2.7.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@openapitools/openapi-generator-cli@2.30.2':
+ dependencies:
+ '@inquirer/select': 1.3.3
+ '@nestjs/axios': 4.0.1(@nestjs/common@11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.6)(rxjs@7.8.2)
+ '@nestjs/common': 11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2)
+ '@nestjs/core': 11.1.16(@nestjs/common@11.1.16(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)
+ '@nuxtjs/opencollective': 0.3.2
+ axios: 1.13.6
+ chalk: 4.1.2
+ commander: 8.3.0
+ compare-versions: 6.1.1
+ concurrently: 9.2.1
+ console.table: 0.10.0
+ fs-extra: 11.3.4
+ glob: 13.0.6
+ proxy-agent: 6.5.0
+ reflect-metadata: 0.2.2
+ rxjs: 7.8.2
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - '@nestjs/microservices'
+ - '@nestjs/platform-express'
+ - '@nestjs/websockets'
+ - class-transformer
+ - class-validator
+ - debug
+ - encoding
+ - supports-color
+
'@opentelemetry/api-logs@0.207.0':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -5867,7 +8732,11 @@ snapshots:
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/api-logs@0.211.0':
+ '@opentelemetry/api-logs@0.212.0':
+ dependencies:
+ '@opentelemetry/api': 1.9.0
+
+ '@opentelemetry/api-logs@0.213.0':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -5882,11 +8751,6 @@ snapshots:
'@opentelemetry/api': 1.9.0
'@opentelemetry/semantic-conventions': 1.40.0
- '@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0)':
- dependencies:
- '@opentelemetry/api': 1.9.0
- '@opentelemetry/semantic-conventions': 1.40.0
-
'@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -5901,163 +8765,163 @@ snapshots:
'@opentelemetry/otlp-transformer': 0.208.0(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-amqplib@0.58.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-amqplib@0.60.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-connect@0.54.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-connect@0.56.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
'@types/connect': 3.4.38
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-dataloader@0.28.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-dataloader@0.30.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-express@0.59.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-express@0.61.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-fs@0.30.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-fs@0.32.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-generic-pool@0.54.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-generic-pool@0.56.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-graphql@0.58.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-graphql@0.61.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-hapi@0.57.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-hapi@0.59.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-http@0.211.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-http@0.213.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
forwarded-parse: 2.1.2
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-ioredis@0.59.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-ioredis@0.61.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/redis-common': 0.38.2
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-kafkajs@0.20.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-kafkajs@0.22.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-knex@0.55.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-knex@0.57.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-koa@0.59.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-koa@0.61.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-lru-memoizer@0.55.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-lru-memoizer@0.57.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-mongodb@0.64.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-mongodb@0.66.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-mongoose@0.57.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-mongoose@0.59.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-mysql2@0.57.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-mysql2@0.59.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
'@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0)
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-mysql@0.57.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-mysql@0.59.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
'@types/mysql': 2.15.27
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-pg@0.63.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-pg@0.65.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
'@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0)
'@types/pg': 8.15.6
@@ -6065,29 +8929,29 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-redis@0.59.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-redis@0.61.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/redis-common': 0.38.2
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-tedious@0.30.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-tedious@0.32.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
'@types/tedious': 4.0.14
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation-undici@0.21.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation-undici@0.23.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
transitivePeerDependencies:
- supports-color
@@ -6101,20 +8965,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation@0.208.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation@0.212.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/api-logs': 0.208.0
+ '@opentelemetry/api-logs': 0.212.0
import-in-the-middle: 2.0.6
require-in-the-middle: 8.0.1
transitivePeerDependencies:
- supports-color
- '@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0)':
+ '@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
- '@opentelemetry/api-logs': 0.211.0
- import-in-the-middle: 2.0.6
+ '@opentelemetry/api-logs': 0.213.0
+ import-in-the-middle: 3.0.0
require-in-the-middle: 8.0.1
transitivePeerDependencies:
- supports-color
@@ -6184,6 +9048,28 @@ snapshots:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
+ '@oslojs/encoding@1.1.0': {}
+
+ '@pagefind/darwin-arm64@1.4.0':
+ optional: true
+
+ '@pagefind/darwin-x64@1.4.0':
+ optional: true
+
+ '@pagefind/default-ui@1.4.0': {}
+
+ '@pagefind/freebsd-x64@1.4.0':
+ optional: true
+
+ '@pagefind/linux-arm64@1.4.0':
+ optional: true
+
+ '@pagefind/linux-x64@1.4.0':
+ optional: true
+
+ '@pagefind/windows-x64@1.4.0':
+ optional: true
+
'@parcel/watcher-android-arm64@2.5.6':
optional: true
@@ -6253,20 +9139,20 @@ snapshots:
dependencies:
playwright: 1.58.2
- '@posthog/core@1.23.3':
+ '@posthog/core@1.24.0':
dependencies:
cross-spawn: 7.0.6
- '@posthog/types@1.360.1': {}
+ '@posthog/types@1.362.0': {}
- '@prisma/client@6.19.2(prisma@6.19.2(typescript@5.9.3))(typescript@5.9.3)':
+ '@prisma/client@6.19.2(prisma@6.19.2(magicast@0.5.2)(typescript@5.9.3))(typescript@5.9.3)':
optionalDependencies:
- prisma: 6.19.2(typescript@5.9.3)
+ prisma: 6.19.2(magicast@0.5.2)(typescript@5.9.3)
typescript: 5.9.3
- '@prisma/config@6.19.2':
+ '@prisma/config@6.19.2(magicast@0.5.2)':
dependencies:
- c12: 3.1.0
+ c12: 3.1.0(magicast@0.5.2)
deepmerge-ts: 7.1.5
effect: 3.18.4
empathic: 2.0.0
@@ -6294,7 +9180,7 @@ snapshots:
dependencies:
'@prisma/debug': 6.19.2
- '@prisma/instrumentation@7.2.0(@opentelemetry/api@1.9.0)':
+ '@prisma/instrumentation@7.4.2(@opentelemetry/api@1.9.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/instrumentation': 0.207.0(@opentelemetry/api@1.9.0)
@@ -6324,6 +9210,18 @@ snapshots:
'@protobufjs/utf8@1.1.0': {}
+ '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4)':
+ dependencies:
+ '@standard-schema/spec': 1.1.0
+ '@standard-schema/utils': 0.3.0
+ immer: 11.1.4
+ redux: 5.0.1
+ redux-thunk: 3.1.0(redux@5.0.1)
+ reselect: 5.1.1
+ optionalDependencies:
+ react: 19.2.4
+ react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1)
+
'@rollup/plugin-commonjs@28.0.1(rollup@4.59.0)':
dependencies:
'@rollup/pluginutils': 5.3.0(rollup@4.59.0)
@@ -6423,33 +9321,33 @@ snapshots:
'@schummar/icu-type-parser@1.21.5': {}
- '@sentry-internal/browser-utils@10.43.0':
+ '@sentry-internal/browser-utils@10.45.0':
dependencies:
- '@sentry/core': 10.43.0
+ '@sentry/core': 10.45.0
- '@sentry-internal/feedback@10.43.0':
+ '@sentry-internal/feedback@10.45.0':
dependencies:
- '@sentry/core': 10.43.0
+ '@sentry/core': 10.45.0
- '@sentry-internal/replay-canvas@10.43.0':
+ '@sentry-internal/replay-canvas@10.45.0':
dependencies:
- '@sentry-internal/replay': 10.43.0
- '@sentry/core': 10.43.0
+ '@sentry-internal/replay': 10.45.0
+ '@sentry/core': 10.45.0
- '@sentry-internal/replay@10.43.0':
+ '@sentry-internal/replay@10.45.0':
dependencies:
- '@sentry-internal/browser-utils': 10.43.0
- '@sentry/core': 10.43.0
+ '@sentry-internal/browser-utils': 10.45.0
+ '@sentry/core': 10.45.0
'@sentry/babel-plugin-component-annotate@5.1.1': {}
- '@sentry/browser@10.43.0':
+ '@sentry/browser@10.45.0':
dependencies:
- '@sentry-internal/browser-utils': 10.43.0
- '@sentry-internal/feedback': 10.43.0
- '@sentry-internal/replay': 10.43.0
- '@sentry-internal/replay-canvas': 10.43.0
- '@sentry/core': 10.43.0
+ '@sentry-internal/browser-utils': 10.45.0
+ '@sentry-internal/feedback': 10.45.0
+ '@sentry-internal/replay': 10.45.0
+ '@sentry-internal/replay-canvas': 10.45.0
+ '@sentry/core': 10.45.0
'@sentry/bundler-plugin-core@5.1.1':
dependencies:
@@ -6508,22 +9406,22 @@ snapshots:
- encoding
- supports-color
- '@sentry/core@10.43.0': {}
+ '@sentry/core@10.45.0': {}
- '@sentry/nextjs@10.43.0(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.105.4)':
+ '@sentry/nextjs@10.45.0(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.105.4)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/semantic-conventions': 1.40.0
'@rollup/plugin-commonjs': 28.0.1(rollup@4.59.0)
- '@sentry-internal/browser-utils': 10.43.0
+ '@sentry-internal/browser-utils': 10.45.0
'@sentry/bundler-plugin-core': 5.1.1
- '@sentry/core': 10.43.0
- '@sentry/node': 10.43.0
- '@sentry/opentelemetry': 10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
- '@sentry/react': 10.43.0(react@19.2.3)
- '@sentry/vercel-edge': 10.43.0
+ '@sentry/core': 10.45.0
+ '@sentry/node': 10.45.0
+ '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
+ '@sentry/react': 10.45.0(react@19.2.4)
+ '@sentry/vercel-edge': 10.45.0
'@sentry/webpack-plugin': 5.1.1(webpack@5.105.4)
- next: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
rollup: 4.59.0
stacktrace-parser: 0.1.11
transitivePeerDependencies:
@@ -6535,80 +9433,80 @@ snapshots:
- supports-color
- webpack
- '@sentry/node-core@10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)':
+ '@sentry/node-core@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)':
dependencies:
- '@sentry/core': 10.43.0
- '@sentry/opentelemetry': 10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
- import-in-the-middle: 2.0.6
+ '@sentry/core': 10.45.0
+ '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
+ import-in-the-middle: 3.0.0
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
'@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
- '@sentry/node@10.43.0':
+ '@sentry/node@10.45.0':
dependencies:
- '@fastify/otel': 0.16.0(@opentelemetry/api@1.9.0)
+ '@fastify/otel': 0.17.1(@opentelemetry/api@1.9.0)
'@opentelemetry/api': 1.9.0
'@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation': 0.211.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-amqplib': 0.58.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-connect': 0.54.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-dataloader': 0.28.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-express': 0.59.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-fs': 0.30.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-generic-pool': 0.54.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-graphql': 0.58.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-hapi': 0.57.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-http': 0.211.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-ioredis': 0.59.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-kafkajs': 0.20.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-knex': 0.55.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-koa': 0.59.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-lru-memoizer': 0.55.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-mongodb': 0.64.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-mongoose': 0.57.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-mysql': 0.57.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-mysql2': 0.57.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-pg': 0.63.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-redis': 0.59.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-tedious': 0.30.0(@opentelemetry/api@1.9.0)
- '@opentelemetry/instrumentation-undici': 0.21.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-amqplib': 0.60.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-connect': 0.56.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-dataloader': 0.30.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-express': 0.61.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-fs': 0.32.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-generic-pool': 0.56.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-graphql': 0.61.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-hapi': 0.59.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-http': 0.213.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-ioredis': 0.61.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-kafkajs': 0.22.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-knex': 0.57.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-koa': 0.61.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-lru-memoizer': 0.57.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-mongodb': 0.66.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-mongoose': 0.59.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-mysql': 0.59.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-mysql2': 0.59.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-pg': 0.65.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-redis': 0.61.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-tedious': 0.32.0(@opentelemetry/api@1.9.0)
+ '@opentelemetry/instrumentation-undici': 0.23.0(@opentelemetry/api@1.9.0)
'@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
- '@prisma/instrumentation': 7.2.0(@opentelemetry/api@1.9.0)
- '@sentry/core': 10.43.0
- '@sentry/node-core': 10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
- '@sentry/opentelemetry': 10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
- import-in-the-middle: 2.0.6
+ '@prisma/instrumentation': 7.4.2(@opentelemetry/api@1.9.0)
+ '@sentry/core': 10.45.0
+ '@sentry/node-core': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
+ '@sentry/opentelemetry': 10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)
+ import-in-the-middle: 3.0.0
transitivePeerDependencies:
- supports-color
- '@sentry/opentelemetry@10.43.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)':
+ '@sentry/opentelemetry@10.45.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.6.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/context-async-hooks': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-base': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.40.0
- '@sentry/core': 10.43.0
+ '@sentry/core': 10.45.0
- '@sentry/react@10.43.0(react@19.2.3)':
+ '@sentry/react@10.45.0(react@19.2.4)':
dependencies:
- '@sentry/browser': 10.43.0
- '@sentry/core': 10.43.0
- react: 19.2.3
+ '@sentry/browser': 10.45.0
+ '@sentry/core': 10.45.0
+ react: 19.2.4
- '@sentry/vercel-edge@10.43.0':
+ '@sentry/vercel-edge@10.45.0':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0)
- '@sentry/core': 10.43.0
+ '@sentry/core': 10.45.0
'@sentry/webpack-plugin@5.1.1(webpack@5.105.4)':
dependencies:
@@ -6619,10 +9517,45 @@ snapshots:
- encoding
- supports-color
+ '@shikijs/core@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.5
+
+ '@shikijs/engine-oniguruma@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+
+ '@shikijs/themes@3.23.0':
+ dependencies:
+ '@shikijs/types': 3.23.0
+
+ '@shikijs/types@3.23.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
'@stablelib/base64@1.0.1': {}
'@standard-schema/spec@1.1.0': {}
+ '@standard-schema/utils@0.3.0': {}
+
'@swc/core-darwin-arm64@1.15.18':
optional: true
@@ -6653,7 +9586,7 @@ snapshots:
'@swc/core-win32-x64-msvc@1.15.18':
optional: true
- '@swc/core@1.15.18(@swc/helpers@0.5.15)':
+ '@swc/core@1.15.18(@swc/helpers@0.5.19)':
dependencies:
'@swc/counter': 0.1.3
'@swc/types': 0.1.25
@@ -6668,7 +9601,7 @@ snapshots:
'@swc/core-win32-arm64-msvc': 1.15.18
'@swc/core-win32-ia32-msvc': 1.15.18
'@swc/core-win32-x64-msvc': 1.15.18
- '@swc/helpers': 0.5.15
+ '@swc/helpers': 0.5.19
'@swc/counter@0.1.3': {}
@@ -6676,10 +9609,43 @@ snapshots:
dependencies:
tslib: 2.8.1
+ '@swc/helpers@0.5.19':
+ dependencies:
+ tslib: 2.8.1
+
'@swc/types@0.1.25':
dependencies:
'@swc/counter': 0.1.3
+ '@tokenizer/inflate@0.4.1':
+ dependencies:
+ debug: 4.4.3
+ token-types: 6.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@tokenizer/token@0.3.0': {}
+
+ '@tootallnate/quickjs-emscripten@0.23.0': {}
+
+ '@turbo/darwin-64@2.8.20':
+ optional: true
+
+ '@turbo/darwin-arm64@2.8.20':
+ optional: true
+
+ '@turbo/linux-64@2.8.20':
+ optional: true
+
+ '@turbo/linux-arm64@2.8.20':
+ optional: true
+
+ '@turbo/windows-64@2.8.20':
+ optional: true
+
+ '@turbo/windows-arm64@2.8.20':
+ optional: true
+
'@tybys/wasm-util@0.10.1':
dependencies:
tslib: 2.8.1
@@ -6693,9 +9659,44 @@ snapshots:
dependencies:
bcryptjs: 3.0.3
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
'@types/connect@3.4.38':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+
+ '@types/d3-array@3.2.2': {}
+
+ '@types/d3-color@3.1.3': {}
+
+ '@types/d3-ease@3.0.2': {}
+
+ '@types/d3-interpolate@3.0.4':
+ dependencies:
+ '@types/d3-color': 3.1.3
+
+ '@types/d3-path@3.1.1': {}
+
+ '@types/d3-scale@4.0.9':
+ dependencies:
+ '@types/d3-time': 3.0.4
+
+ '@types/d3-shape@3.1.8':
+ dependencies:
+ '@types/d3-path': 3.1.1
+
+ '@types/d3-time@3.0.4': {}
+
+ '@types/d3-timer@3.0.2': {}
+
+ '@types/debug@4.1.12':
+ dependencies:
+ '@types/ms': 2.1.0
+
+ '@types/deep-eql@4.0.2': {}
'@types/eslint-scope@3.7.7':
dependencies:
@@ -6707,15 +9708,43 @@ snapshots:
'@types/estree': 1.0.8
'@types/json-schema': 7.0.15
+ '@types/estree-jsx@1.0.5':
+ dependencies:
+ '@types/estree': 1.0.8
+
'@types/estree@1.0.8': {}
+ '@types/geoip-lite@1.4.4': {}
+
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/js-yaml@4.0.9': {}
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdx@2.0.13': {}
+
+ '@types/ms@2.1.0': {}
+
+ '@types/mute-stream@0.0.4':
+ dependencies:
+ '@types/node': 25.5.0
+
'@types/mysql@2.15.27':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+
+ '@types/nlcst@2.0.3':
+ dependencies:
+ '@types/unist': 3.0.3
'@types/node@12.20.55': {}
@@ -6723,9 +9752,17 @@ snapshots:
dependencies:
undici-types: 6.21.0
+ '@types/node@24.12.0':
+ dependencies:
+ undici-types: 7.16.0
+
+ '@types/node@25.5.0':
+ dependencies:
+ undici-types: 7.18.2
+
'@types/pdfkit@0.17.5':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
'@types/pg-pool@2.0.7':
dependencies:
@@ -6733,13 +9770,13 @@ snapshots:
'@types/pg@8.15.6':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
pg-protocol: 1.13.0
pg-types: 2.2.0
'@types/qrcode@1.5.6':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
'@types/react-dom@19.2.3(@types/react@19.2.14)':
dependencies:
@@ -6751,106 +9788,120 @@ snapshots:
'@types/readdir-glob@1.1.5':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+
+ '@types/sax@1.2.7':
+ dependencies:
+ '@types/node': 25.5.0
'@types/tedious@4.0.14':
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
'@types/trusted-types@2.0.7':
optional: true
- '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
+ '@types/unist@2.0.11': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@types/use-sync-external-store@0.0.6': {}
+
+ '@types/wrap-ansi@3.0.0': {}
+
+ '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/scope-manager': 8.56.1
- '@typescript-eslint/type-utils': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.56.1
+ '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.57.2
+ '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.57.2
eslint: 9.39.4(jiti@2.6.1)
ignore: 7.0.5
natural-compare: 1.4.0
- ts-api-utils: 2.4.0(typescript@5.9.3)
+ ts-api-utils: 2.5.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.56.1
- '@typescript-eslint/types': 8.56.1
- '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.56.1
+ '@typescript-eslint/scope-manager': 8.57.2
+ '@typescript-eslint/types': 8.57.2
+ '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.57.2
debug: 4.4.3
eslint: 9.39.4(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.56.1(typescript@5.9.3)':
+ '@typescript-eslint/project-service@8.57.2(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/types': 8.56.1
+ '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/types': 8.57.2
debug: 4.4.3
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.56.1':
+ '@typescript-eslint/scope-manager@8.57.2':
dependencies:
- '@typescript-eslint/types': 8.56.1
- '@typescript-eslint/visitor-keys': 8.56.1
+ '@typescript-eslint/types': 8.57.2
+ '@typescript-eslint/visitor-keys': 8.57.2
- '@typescript-eslint/tsconfig-utils@8.56.1(typescript@5.9.3)':
+ '@typescript-eslint/tsconfig-utils@8.57.2(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
- '@typescript-eslint/type-utils@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/types': 8.56.1
- '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/types': 8.57.2
+ '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3
eslint: 9.39.4(jiti@2.6.1)
- ts-api-utils: 2.4.0(typescript@5.9.3)
+ ts-api-utils: 2.5.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.56.1': {}
+ '@typescript-eslint/types@8.57.2': {}
- '@typescript-eslint/typescript-estree@8.56.1(typescript@5.9.3)':
+ '@typescript-eslint/typescript-estree@8.57.2(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/project-service': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/types': 8.56.1
- '@typescript-eslint/visitor-keys': 8.56.1
+ '@typescript-eslint/project-service': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/types': 8.57.2
+ '@typescript-eslint/visitor-keys': 8.57.2
debug: 4.4.3
minimatch: 10.2.4
semver: 7.7.4
tinyglobby: 0.2.15
- ts-api-utils: 2.4.0(typescript@5.9.3)
+ ts-api-utils: 2.5.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.56.1
- '@typescript-eslint/types': 8.56.1
- '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.57.2
+ '@typescript-eslint/types': 8.57.2
+ '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3)
eslint: 9.39.4(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.56.1':
+ '@typescript-eslint/visitor-keys@8.57.2':
dependencies:
- '@typescript-eslint/types': 8.56.1
+ '@typescript-eslint/types': 8.57.2
eslint-visitor-keys: 5.0.1
+ '@ungap/structured-clone@1.3.0': {}
+
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
optional: true
@@ -6917,39 +9968,130 @@ snapshots:
chai: 5.3.3
tinyrainbow: 1.2.0
- '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@20.19.37)(terser@5.46.0))':
+ '@vitest/expect@4.1.0':
+ dependencies:
+ '@standard-schema/spec': 1.1.0
+ '@types/chai': 5.2.3
+ '@vitest/spy': 4.1.0
+ '@vitest/utils': 4.1.0
+ chai: 6.2.2
+ tinyrainbow: 3.1.0
+
+ '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@25.5.0)(terser@5.46.1))':
dependencies:
'@vitest/spy': 2.1.9
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 5.4.21(@types/node@20.19.37)(terser@5.46.0)
+ vite: 5.4.21(@types/node@25.5.0)(terser@5.46.1)
+
+ '@vitest/mocker@4.1.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))':
+ dependencies:
+ '@vitest/spy': 4.1.0
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)
'@vitest/pretty-format@2.1.9':
dependencies:
tinyrainbow: 1.2.0
+ '@vitest/pretty-format@4.1.0':
+ dependencies:
+ tinyrainbow: 3.1.0
+
'@vitest/runner@2.1.9':
dependencies:
'@vitest/utils': 2.1.9
pathe: 1.1.2
+ '@vitest/runner@4.1.0':
+ dependencies:
+ '@vitest/utils': 4.1.0
+ pathe: 2.0.3
+
'@vitest/snapshot@2.1.9':
dependencies:
'@vitest/pretty-format': 2.1.9
magic-string: 0.30.21
pathe: 1.1.2
+ '@vitest/snapshot@4.1.0':
+ dependencies:
+ '@vitest/pretty-format': 4.1.0
+ '@vitest/utils': 4.1.0
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
'@vitest/spy@2.1.9':
dependencies:
tinyspy: 3.0.2
+ '@vitest/spy@4.1.0': {}
+
'@vitest/utils@2.1.9':
dependencies:
'@vitest/pretty-format': 2.1.9
loupe: 3.2.1
tinyrainbow: 1.2.0
+ '@vitest/utils@4.1.0':
+ dependencies:
+ '@vitest/pretty-format': 4.1.0
+ convert-source-map: 2.0.0
+ tinyrainbow: 3.1.0
+
+ '@volar/kit@2.4.28(typescript@5.9.3)':
+ dependencies:
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ typesafe-path: 0.2.2
+ typescript: 5.9.3
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-core@2.4.28':
+ dependencies:
+ '@volar/source-map': 2.4.28
+
+ '@volar/language-server@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ path-browserify: 1.0.1
+ request-light: 0.7.0
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-service@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/source-map@2.4.28': {}
+
+ '@volar/typescript@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ path-browserify: 1.0.1
+ vscode-uri: 3.1.0
+
+ '@vscode/emmet-helper@2.11.0':
+ dependencies:
+ emmet: 2.4.11
+ jsonc-parser: 2.3.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ '@vscode/l10n@0.0.18': {}
+
'@webassemblyjs/ast@1.14.1':
dependencies:
'@webassemblyjs/helper-numbers': 1.13.2
@@ -7026,6 +10168,8 @@ snapshots:
'@webassemblyjs/ast': 1.14.1
'@xtuc/long': 4.2.2
+ '@xmldom/xmldom@0.8.11': {}
+
'@xtuc/ieee754@1.2.0': {}
'@xtuc/long@4.2.2': {}
@@ -7056,11 +10200,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ajv-formats@2.1.1(ajv@8.18.0):
+ agent-base@7.1.4: {}
+
+ ajv-draft-04@1.0.0(ajv@8.18.0):
optionalDependencies:
ajv: 8.18.0
- ajv-formats@3.0.1(ajv@8.18.0):
+ ajv-formats@2.1.1(ajv@8.18.0):
+ optionalDependencies:
+ ajv: 8.18.0
+
+ ajv-formats@3.0.1(ajv@8.18.0):
optionalDependencies:
ajv: 8.18.0
@@ -7083,8 +10233,16 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
+ ansi-align@3.0.1:
+ dependencies:
+ string-width: 4.2.3
+
ansi-colors@4.1.3: {}
+ ansi-escapes@4.3.2:
+ dependencies:
+ type-fest: 0.21.3
+
ansi-escapes@7.3.0:
dependencies:
environment: 1.1.0
@@ -7101,6 +10259,11 @@ snapshots:
any-promise@1.3.0: {}
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
archiver-utils@5.0.2:
dependencies:
glob: 10.5.0
@@ -7125,6 +10288,8 @@ snapshots:
- bare-buffer
- react-native-b4a
+ arg@5.0.2: {}
+
argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
@@ -7149,6 +10314,8 @@ snapshots:
is-string: 1.1.1
math-intrinsics: 1.1.0
+ array-iterate@2.0.1: {}
+
array-union@2.1.0: {}
array.prototype.findlast@1.2.5:
@@ -7213,6 +10380,119 @@ snapshots:
ast-types-flow@0.0.8: {}
+ ast-types@0.13.4:
+ dependencies:
+ tslib: 2.8.1
+
+ astring@1.9.0: {}
+
+ astro-expressive-code@0.41.7(astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)):
+ dependencies:
+ astro: 5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
+ rehype-expressive-code: 0.41.7
+
+ astro@5.18.1(@types/node@25.5.0)(jiti@2.6.1)(rollup@4.59.0)(terser@5.46.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2):
+ dependencies:
+ '@astrojs/compiler': 2.13.1
+ '@astrojs/internal-helpers': 0.7.6
+ '@astrojs/markdown-remark': 6.3.11
+ '@astrojs/telemetry': 3.3.0
+ '@capsizecss/unpack': 4.0.0
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.3.0(rollup@4.59.0)
+ acorn: 8.16.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ boxen: 8.0.1
+ ci-info: 4.4.0
+ clsx: 2.1.1
+ common-ancestor-path: 1.0.1
+ cookie: 1.1.1
+ cssesc: 3.0.0
+ debug: 4.4.3
+ deterministic-object-hash: 2.0.2
+ devalue: 5.6.4
+ diff: 8.0.3
+ dlv: 1.1.3
+ dset: 3.1.4
+ es-module-lexer: 1.7.0
+ esbuild: 0.27.3
+ estree-walker: 3.0.3
+ flattie: 1.1.1
+ fontace: 0.4.1
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ magic-string: 0.30.21
+ magicast: 0.5.2
+ mrmime: 2.0.1
+ neotraverse: 0.6.18
+ p-limit: 6.2.0
+ p-queue: 8.1.1
+ package-manager-detector: 1.6.0
+ piccolore: 0.1.3
+ picomatch: 4.0.3
+ prompts: 2.4.2
+ rehype: 13.0.2
+ semver: 7.7.4
+ shiki: 3.23.0
+ smol-toml: 1.6.0
+ svgo: 4.0.1
+ tinyexec: 1.0.4
+ tinyglobby: 0.2.15
+ tsconfck: 3.1.6(typescript@5.9.3)
+ ultrahtml: 1.6.0
+ unifont: 0.7.4
+ unist-util-visit: 5.1.0
+ unstorage: 1.17.4
+ vfile: 6.0.3
+ vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)
+ vitefu: 1.1.2(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 21.1.1
+ yocto-spinner: 0.2.3
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.1(zod@3.25.76)
+ zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76)
+ optionalDependencies:
+ sharp: 0.34.5
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - lightningcss
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - typescript
+ - uploadthing
+ - yaml
+
async-function@1.0.0: {}
async@3.2.6: {}
@@ -7244,6 +10524,8 @@ snapshots:
b4a@1.8.0: {}
+ bail@2.0.2: {}
+
balanced-match@1.0.2: {}
balanced-match@4.0.4: {}
@@ -7281,11 +10563,23 @@ snapshots:
dependencies:
bare-path: 3.0.0
+ base-64@1.0.0: {}
+
base64-js@0.0.8: {}
base64-js@1.5.1: {}
- baseline-browser-mapping@2.10.0: {}
+ baseline-browser-mapping@2.10.9: {}
+
+ basic-ftp@5.2.0: {}
+
+ bcp-47-match@2.0.3: {}
+
+ bcp-47@2.1.0:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
bcryptjs@3.0.3: {}
@@ -7293,8 +10587,23 @@ snapshots:
dependencies:
is-windows: 1.0.2
+ bluebird@3.7.2: {}
+
bn.js@4.12.3: {}
+ boolbase@1.0.0: {}
+
+ boxen@8.0.1:
+ dependencies:
+ ansi-align: 3.0.1
+ camelcase: 8.0.0
+ chalk: 5.6.2
+ cli-boxes: 3.0.0
+ string-width: 7.2.0
+ type-fest: 4.41.0
+ widest-line: 5.0.0
+ wrap-ansi: 9.0.2
+
brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
@@ -7318,12 +10627,14 @@ snapshots:
browserslist@4.28.1:
dependencies:
- baseline-browser-mapping: 2.10.0
- caniuse-lite: 1.0.30001777
- electron-to-chromium: 1.5.307
+ baseline-browser-mapping: 2.10.9
+ caniuse-lite: 1.0.30001780
+ electron-to-chromium: 1.5.321
node-releases: 2.0.36
update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ buffer-crc32@0.2.13: {}
+
buffer-crc32@1.0.0: {}
buffer-from@1.1.2: {}
@@ -7338,7 +10649,7 @@ snapshots:
esbuild: 0.27.3
load-tsconfig: 0.2.5
- c12@3.1.0:
+ c12@3.1.0(magicast@0.5.2):
dependencies:
chokidar: 4.0.3
confbox: 0.2.4
@@ -7352,6 +10663,8 @@ snapshots:
perfect-debounce: 1.0.0
pkg-types: 2.3.0
rc9: 2.1.2
+ optionalDependencies:
+ magicast: 0.5.2
cac@6.7.14: {}
@@ -7376,9 +10689,13 @@ snapshots:
camelcase@5.3.1: {}
- caniuse-lite@1.0.30001777: {}
+ camelcase@8.0.0: {}
+
+ caniuse-lite@1.0.30001780: {}
- ccxt@4.5.42:
+ ccount@2.0.1: {}
+
+ ccxt@4.5.44:
dependencies:
ws: 8.19.0
transitivePeerDependencies:
@@ -7393,11 +10710,23 @@ snapshots:
loupe: 3.2.1
pathval: 2.0.1
+ chai@6.2.2: {}
+
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
+ chalk@5.6.2: {}
+
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ character-entities@2.0.2: {}
+
+ character-reference-invalid@2.0.1: {}
+
chardet@2.1.1: {}
check-error@2.1.3: {}
@@ -7406,8 +10735,14 @@ snapshots:
dependencies:
readdirp: 4.1.2
+ chokidar@5.0.0:
+ dependencies:
+ readdirp: 5.0.0
+
chrome-trace-event@1.0.4: {}
+ ci-info@4.4.0: {}
+
citty@0.1.6:
dependencies:
consola: 3.4.2
@@ -7416,15 +10751,21 @@ snapshots:
cjs-module-lexer@2.2.0: {}
+ cli-boxes@3.0.0: {}
+
cli-cursor@5.0.0:
dependencies:
restore-cursor: 5.1.0
+ cli-spinners@2.9.2: {}
+
cli-truncate@5.2.0:
dependencies:
slice-ansi: 8.0.0
string-width: 8.2.0
+ cli-width@4.1.0: {}
+
client-only@0.0.1: {}
cliui@6.0.0:
@@ -7433,28 +10774,61 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ clone@1.0.4:
+ optional: true
+
clone@2.1.2: {}
+ clsx@2.1.1: {}
+
+ collapse-white-space@2.1.0: {}
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
+ color-string@1.9.1:
+ dependencies:
+ color-name: 1.1.4
+ simple-swizzle: 0.2.4
+
+ color@4.2.3:
+ dependencies:
+ color-convert: 2.0.1
+ color-string: 1.9.1
+
colorette@2.0.20: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
+ comma-separated-tokens@2.0.3: {}
+
+ commander@11.1.0: {}
+
commander@14.0.3: {}
commander@2.20.3: {}
commander@4.1.1: {}
+ commander@8.3.0: {}
+
+ common-ancestor-path@1.0.1: {}
+
commondir@1.0.1: {}
+ compare-versions@6.1.1: {}
+
compress-commons@6.0.2:
dependencies:
crc-32: 1.2.2
@@ -7465,19 +10839,36 @@ snapshots:
concat-map@0.0.1: {}
+ concurrently@9.2.1:
+ dependencies:
+ chalk: 4.1.2
+ rxjs: 7.8.2
+ shell-quote: 1.8.3
+ supports-color: 8.1.1
+ tree-kill: 1.2.2
+ yargs: 17.7.2
+
confbox@0.1.8: {}
confbox@0.2.4: {}
+ consola@2.15.3: {}
+
consola@3.4.2: {}
+ console.table@0.10.0:
+ dependencies:
+ easy-table: 1.1.0
+
content-disposition@1.0.1: {}
convert-source-map@2.0.0: {}
+ cookie-es@1.2.2: {}
+
cookie@1.1.1: {}
- core-js@3.48.0: {}
+ core-js@3.49.0: {}
core-util-is@1.0.3: {}
@@ -7494,12 +10885,82 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
- crypto-js@4.2.0: {}
+ crossws@0.3.5:
+ dependencies:
+ uncrypto: 0.1.3
+
+ css-select@5.2.2:
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.2.2
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ nth-check: 2.1.1
+
+ css-selector-parser@3.3.0: {}
+
+ css-tree@2.2.1:
+ dependencies:
+ mdn-data: 2.0.28
+ source-map-js: 1.2.1
+
+ css-tree@3.2.1:
+ dependencies:
+ mdn-data: 2.27.1
+ source-map-js: 1.2.1
+
+ css-what@6.2.2: {}
+
+ cssesc@3.0.0: {}
+
+ csso@5.0.5:
+ dependencies:
+ css-tree: 2.2.1
csstype@3.2.3: {}
+ d3-array@3.2.4:
+ dependencies:
+ internmap: 2.0.3
+
+ d3-color@3.1.0: {}
+
+ d3-ease@3.0.1: {}
+
+ d3-format@3.1.2: {}
+
+ d3-interpolate@3.0.1:
+ dependencies:
+ d3-color: 3.1.0
+
+ d3-path@3.1.0: {}
+
+ d3-scale@4.0.2:
+ dependencies:
+ d3-array: 3.2.4
+ d3-format: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+
+ d3-shape@3.2.0:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-time-format@4.1.0:
+ dependencies:
+ d3-time: 3.1.0
+
+ d3-time@3.1.0:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-timer@3.0.1: {}
+
damerau-levenshtein@1.0.8: {}
+ data-uri-to-buffer@6.0.2: {}
+
data-view-buffer@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -7532,14 +10993,25 @@ snapshots:
decamelize@1.2.0: {}
+ decimal.js-light@2.5.1: {}
+
decimal.js@10.6.0: {}
+ decode-named-character-reference@1.3.0:
+ dependencies:
+ character-entities: 2.0.2
+
deep-eql@5.0.2: {}
deep-is@0.1.4: {}
deepmerge-ts@7.1.5: {}
+ defaults@1.0.4:
+ dependencies:
+ clone: 1.0.4
+ optional: true
+
define-data-property@1.1.4:
dependencies:
es-define-property: 1.0.1
@@ -7554,6 +11026,12 @@ snapshots:
defu@6.1.4: {}
+ degenerator@5.0.1:
+ dependencies:
+ ast-types: 0.13.4
+ escodegen: 2.1.0
+ esprima: 4.0.1
+
delayed-stream@1.0.0: {}
depd@2.0.0: {}
@@ -7566,34 +11044,80 @@ snapshots:
detect-libc@2.1.2: {}
+ deterministic-object-hash@2.0.2:
+ dependencies:
+ base-64: 1.0.0
+
+ devalue@5.6.4: {}
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
dfa@1.2.0: {}
+ diff@8.0.3: {}
+
dijkstrajs@1.0.3: {}
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
+ direction@2.0.1: {}
+
+ dlv@1.1.3: {}
+
doctrine@2.1.0:
dependencies:
esutils: 2.0.3
+ dom-serializer@2.0.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+
+ domelementtype@2.3.0: {}
+
+ domhandler@5.0.3:
+ dependencies:
+ domelementtype: 2.3.0
+
dompurify@3.3.3:
optionalDependencies:
'@types/trusted-types': 2.0.7
+ domutils@3.2.2:
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+
dotenv@16.6.1: {}
+ dotenv@17.3.1: {}
+
dotenv@8.6.0: {}
+ dset@3.1.4: {}
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
es-errors: 1.3.0
gopd: 1.2.0
+ duplexer2@0.1.4:
+ dependencies:
+ readable-stream: 2.3.8
+
eastasianwidth@0.2.0: {}
+ easy-table@1.1.0:
+ optionalDependencies:
+ wcwidth: 1.0.1
+
ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer: 5.2.1
@@ -7603,7 +11127,12 @@ snapshots:
'@standard-schema/spec': 1.1.0
fast-check: 3.23.2
- electron-to-chromium@1.5.307: {}
+ electron-to-chromium@1.5.321: {}
+
+ emmet@2.4.11:
+ dependencies:
+ '@emmetio/abbreviation': 2.3.3
+ '@emmetio/css-abbreviation': 2.1.8
emoji-regex@10.6.0: {}
@@ -7617,7 +11146,7 @@ snapshots:
dependencies:
once: 1.4.0
- enhanced-resolve@5.20.0:
+ enhanced-resolve@5.20.1:
dependencies:
graceful-fs: 4.2.11
tapable: 2.3.0
@@ -7627,6 +11156,10 @@ snapshots:
ansi-colors: 4.1.3
strip-ansi: 6.0.1
+ entities@4.5.0: {}
+
+ entities@6.0.1: {}
+
environment@1.1.0: {}
es-abstract@1.24.1:
@@ -7690,7 +11223,7 @@ snapshots:
es-errors@1.3.0: {}
- es-iterator-helpers@1.2.2:
+ es-iterator-helpers@1.3.1:
dependencies:
call-bind: 1.0.8
call-bound: 1.0.4
@@ -7707,6 +11240,7 @@ snapshots:
has-symbols: 1.1.0
internal-slot: 1.1.0
iterator.prototype: 1.1.5
+ math-intrinsics: 1.1.0
safe-array-concat: 1.1.3
es-module-lexer@1.7.0: {}
@@ -7734,6 +11268,22 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
+ es-toolkit@1.45.1: {}
+
+ esast-util-from-estree@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ unist-util-position-from-estree: 2.0.0
+
+ esast-util-from-js@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ acorn: 8.16.0
+ esast-util-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
@@ -7760,6 +11310,35 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
+ esbuild@0.25.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.12
+ '@esbuild/android-arm': 0.25.12
+ '@esbuild/android-arm64': 0.25.12
+ '@esbuild/android-x64': 0.25.12
+ '@esbuild/darwin-arm64': 0.25.12
+ '@esbuild/darwin-x64': 0.25.12
+ '@esbuild/freebsd-arm64': 0.25.12
+ '@esbuild/freebsd-x64': 0.25.12
+ '@esbuild/linux-arm': 0.25.12
+ '@esbuild/linux-arm64': 0.25.12
+ '@esbuild/linux-ia32': 0.25.12
+ '@esbuild/linux-loong64': 0.25.12
+ '@esbuild/linux-mips64el': 0.25.12
+ '@esbuild/linux-ppc64': 0.25.12
+ '@esbuild/linux-riscv64': 0.25.12
+ '@esbuild/linux-s390x': 0.25.12
+ '@esbuild/linux-x64': 0.25.12
+ '@esbuild/netbsd-arm64': 0.25.12
+ '@esbuild/netbsd-x64': 0.25.12
+ '@esbuild/openbsd-arm64': 0.25.12
+ '@esbuild/openbsd-x64': 0.25.12
+ '@esbuild/openharmony-arm64': 0.25.12
+ '@esbuild/sunos-x64': 0.25.12
+ '@esbuild/win32-arm64': 0.25.12
+ '@esbuild/win32-ia32': 0.25.12
+ '@esbuild/win32-x64': 0.25.12
+
esbuild@0.27.3:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.3
@@ -7793,20 +11372,32 @@ snapshots:
escape-html@1.0.3: {}
+ escape-string-regexp@1.0.5: {}
+
escape-string-regexp@4.0.0: {}
- eslint-config-next@16.1.6(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
+ escape-string-regexp@5.0.0: {}
+
+ escodegen@2.1.0:
+ dependencies:
+ esprima: 4.0.1
+ estraverse: 5.3.0
+ esutils: 2.0.3
+ optionalDependencies:
+ source-map: 0.6.1
+
+ eslint-config-next@16.2.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@next/eslint-plugin-next': 16.1.6
+ '@next/eslint-plugin-next': 16.2.0
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.4(jiti@2.6.1))
globals: 16.4.0
- typescript-eslint: 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ typescript-eslint: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
@@ -7834,22 +11425,22 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -7860,7 +11451,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.4(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -7872,7 +11463,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -7900,11 +11491,11 @@ snapshots:
eslint-plugin-react-hooks@7.0.1(eslint@9.39.4(jiti@2.6.1)):
dependencies:
'@babel/core': 7.29.0
- '@babel/parser': 7.29.0
+ '@babel/parser': 7.29.2
eslint: 9.39.4(jiti@2.6.1)
hermes-parser: 0.25.1
- zod: 3.25.76
- zod-validation-error: 4.0.2(zod@3.25.76)
+ zod: 4.3.6
+ zod-validation-error: 4.0.2(zod@4.3.6)
transitivePeerDependencies:
- supports-color
@@ -7915,7 +11506,7 @@ snapshots:
array.prototype.flatmap: 1.3.3
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
- es-iterator-helpers: 1.2.2
+ es-iterator-helpers: 1.3.1
eslint: 9.39.4(jiti@2.6.1)
estraverse: 5.3.0
hasown: 2.0.2
@@ -8007,6 +11598,35 @@ snapshots:
estraverse@5.3.0: {}
+ estree-util-attach-comments@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ estree-util-build-jsx@3.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-walker: 3.0.3
+
+ estree-util-is-identifier-name@3.0.0: {}
+
+ estree-util-scope@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+
+ estree-util-to-js@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ astring: 1.9.0
+ source-map: 0.7.6
+
+ estree-util-visit@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/unist': 3.0.3
+
estree-walker@2.0.2: {}
estree-walker@3.0.3:
@@ -8029,8 +11649,21 @@ snapshots:
expect-type@1.3.0: {}
+ expressive-code@0.41.7:
+ dependencies:
+ '@expressive-code/core': 0.41.7
+ '@expressive-code/plugin-frames': 0.41.7
+ '@expressive-code/plugin-shiki': 0.41.7
+ '@expressive-code/plugin-text-markers': 0.41.7
+
exsolve@1.0.8: {}
+ extend-shallow@2.0.1:
+ dependencies:
+ is-extendable: 0.1.1
+
+ extend@3.0.2: {}
+
extendable-error@0.1.7: {}
fast-check@3.23.2:
@@ -8053,6 +11686,14 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.8
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
fast-json-stable-stringify@2.1.0: {}
fast-json-stringify@6.3.0:
@@ -8089,19 +11730,19 @@ snapshots:
fastify-plugin@5.1.0: {}
- fastify-zod-openapi@4.1.2(@fastify/swagger-ui@5.2.5)(@fastify/swagger@9.7.0)(fastify@5.8.1)(zod-openapi@4.2.4(zod@3.25.76))(zod@3.25.76):
+ fastify-zod-openapi@5.5.0(@fastify/swagger-ui@5.2.5)(@fastify/swagger@9.7.0)(fastify@5.8.2)(zod@4.3.6):
dependencies:
'@fastify/error': 4.2.0
fast-json-stringify: 6.3.0
- fastify: 5.8.1
+ fastify: 5.8.2
fastify-plugin: 5.1.0
- zod: 3.25.76
- zod-openapi: 4.2.4(zod@3.25.76)
+ zod: 4.3.6
+ zod-openapi: 5.4.6(zod@4.3.6)
optionalDependencies:
'@fastify/swagger': 9.7.0
'@fastify/swagger-ui': 5.2.5
- fastify@5.8.1:
+ fastify@5.8.2:
dependencies:
'@fastify/ajv-compiler': 4.0.5
'@fastify/error': 4.2.0
@@ -8139,10 +11780,25 @@ snapshots:
fflate@0.4.8: {}
+ fflate@0.8.2: {}
+
+ figures@3.2.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
+ file-type@21.3.0:
+ dependencies:
+ '@tokenizer/inflate': 0.4.1
+ strtok3: 10.3.5
+ token-types: 6.1.2
+ uint8array-extras: 1.5.0
+ transitivePeerDependencies:
+ - supports-color
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
@@ -8151,7 +11807,7 @@ snapshots:
dependencies:
fast-deep-equal: 3.1.3
fast-querystring: 1.1.2
- safe-regex2: 5.0.0
+ safe-regex2: 5.1.0
find-up@4.1.0:
dependencies:
@@ -8171,16 +11827,22 @@ snapshots:
flat-cache@4.0.1:
dependencies:
- flatted: 3.3.4
+ flatted: 3.4.2
keyv: 4.5.4
- flatted@3.3.4: {}
+ flatted@3.4.2: {}
+
+ flattie@1.1.1: {}
follow-redirects@1.15.11: {}
+ fontace@0.4.1:
+ dependencies:
+ fontkitten: 1.0.3
+
fontkit@2.0.4:
dependencies:
- '@swc/helpers': 0.5.15
+ '@swc/helpers': 0.5.19
brotli: 1.3.3
clone: 2.1.2
dfa: 1.2.0
@@ -8190,6 +11852,10 @@ snapshots:
unicode-properties: 1.4.1
unicode-trie: 2.0.0
+ fontkitten@1.0.3:
+ dependencies:
+ tiny-inflate: 1.0.3
+
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
@@ -8209,6 +11875,12 @@ snapshots:
forwarded-parse@2.1.2: {}
+ fs-extra@11.3.4:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.0
+ universalify: 2.0.1
+
fs-extra@7.0.1:
dependencies:
graceful-fs: 4.2.11
@@ -8244,6 +11916,14 @@ snapshots:
gensync@1.0.0-beta.2: {}
+ geoip-lite@2.0.1:
+ dependencies:
+ chalk: 4.1.2
+ iconv-lite: 0.6.3
+ ip-address: 5.9.4
+ lazy: 1.0.11
+ yauzl: 3.2.1
+
get-caller-file@2.0.5: {}
get-east-asian-width@1.5.0: {}
@@ -8276,6 +11956,14 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
+ get-uri@6.0.5:
+ dependencies:
+ basic-ftp: 5.2.0
+ data-uri-to-buffer: 6.0.2
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
giget@2.0.0:
dependencies:
citty: 0.1.6
@@ -8285,6 +11973,8 @@ snapshots:
nypm: 0.6.5
pathe: 2.0.3
+ github-slugger@2.0.0: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -8323,7 +12013,7 @@ snapshots:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
- fast-glob: 3.3.1
+ fast-glob: 3.3.3
ignore: 5.3.2
merge2: 1.4.1
slash: 3.0.0
@@ -8332,7 +12022,26 @@ snapshots:
graceful-fs@4.2.11: {}
- has-bigints@1.1.0: {}
+ gray-matter@4.0.3:
+ dependencies:
+ js-yaml: 3.14.2
+ kind-of: 6.0.3
+ section-matter: 1.0.0
+ strip-bom-string: 1.0.0
+
+ h3@1.15.9:
+ dependencies:
+ cookie-es: 1.2.2
+ crossws: 0.3.5
+ defu: 6.1.4
+ destr: 2.0.5
+ iron-webcrypto: 1.2.1
+ node-mock-http: 1.0.4
+ radix3: 1.1.2
+ ufo: 1.6.3
+ uncrypto: 0.1.3
+
+ has-bigints@1.1.0: {}
has-flag@4.0.0: {}
@@ -8354,6 +12063,195 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hast-util-embedded@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-is-element: 3.0.0
+
+ hast-util-format@1.1.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-embedded: 3.0.0
+ hast-util-minify-whitespace: 1.0.1
+ hast-util-phrasing: 3.0.1
+ hast-util-whitespace: 3.0.0
+ html-whitespace-sensitive-tag-names: 3.0.1
+ unist-util-visit-parents: 6.0.2
+
+ hast-util-from-html@2.0.3:
+ dependencies:
+ '@types/hast': 3.0.4
+ devlop: 1.1.0
+ hast-util-from-parse5: 8.0.3
+ parse5: 7.3.0
+ vfile: 6.0.3
+ vfile-message: 4.0.3
+
+ hast-util-from-parse5@8.0.3:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ hastscript: 9.0.1
+ property-information: 7.1.0
+ vfile: 6.0.3
+ vfile-location: 5.0.3
+ web-namespaces: 2.0.1
+
+ hast-util-has-property@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-is-body-ok-link@3.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-is-element@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-minify-whitespace@1.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-embedded: 3.0.0
+ hast-util-is-element: 3.0.0
+ hast-util-whitespace: 3.0.0
+ unist-util-is: 6.0.1
+
+ hast-util-parse-selector@4.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-phrasing@3.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-embedded: 3.0.0
+ hast-util-has-property: 3.0.0
+ hast-util-is-body-ok-link: 3.0.1
+ hast-util-is-element: 3.0.0
+
+ hast-util-raw@9.1.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ '@ungap/structured-clone': 1.3.0
+ hast-util-from-parse5: 8.0.3
+ hast-util-to-parse5: 8.0.1
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ parse5: 7.3.0
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-select@6.0.4:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ bcp-47-match: 2.0.3
+ comma-separated-tokens: 2.0.3
+ css-selector-parser: 3.3.0
+ devlop: 1.1.0
+ direction: 2.0.1
+ hast-util-has-property: 3.0.0
+ hast-util-to-string: 3.0.1
+ hast-util-whitespace: 3.0.0
+ nth-check: 2.1.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ unist-util-visit: 5.1.0
+ zwitch: 2.0.4
+
+ hast-util-to-estree@3.1.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-attach-comments: 3.0.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ zwitch: 2.0.4
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-to-jsx-runtime@2.3.6:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-parse5@8.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-to-string@3.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-to-text@4.0.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ hast-util-is-element: 3.0.0
+ unist-util-find-after: 5.0.0
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hastscript@9.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ hast-util-parse-selector: 4.0.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+
help-me@5.0.0: {}
hermes-estree@0.25.1: {}
@@ -8362,6 +12260,16 @@ snapshots:
dependencies:
hermes-estree: 0.25.1
+ html-escaper@3.0.3: {}
+
+ html-url-attributes@3.0.1: {}
+
+ html-void-elements@3.0.0: {}
+
+ html-whitespace-sensitive-tag-names@3.0.1: {}
+
+ http-cache-semantics@4.2.0: {}
+
http-errors@2.0.1:
dependencies:
depd: 2.0.0
@@ -8370,6 +12278,13 @@ snapshots:
statuses: 2.0.2
toidentifier: 1.0.1
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
@@ -8377,10 +12292,25 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
human-id@4.1.3: {}
husky@9.1.7: {}
+ i18next@23.16.8:
+ dependencies:
+ '@babel/runtime': 7.29.2
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
iconv-lite@0.7.2:
dependencies:
safer-buffer: 2.1.2
@@ -8395,6 +12325,10 @@ snapshots:
ignore@7.0.5: {}
+ immer@10.2.0: {}
+
+ immer@11.1.4: {}
+
import-fresh@3.3.1:
dependencies:
parent-module: 1.0.1
@@ -8407,16 +12341,29 @@ snapshots:
cjs-module-lexer: 2.2.0
module-details-from-path: 1.0.4
+ import-in-the-middle@3.0.0:
+ dependencies:
+ acorn: 8.16.0
+ acorn-import-attributes: 1.9.5(acorn@8.16.0)
+ cjs-module-lexer: 2.2.0
+ module-details-from-path: 1.0.4
+
+ import-meta-resolve@4.2.0: {}
+
imurmurhash@0.1.4: {}
inherits@2.0.4: {}
+ inline-style-parser@0.2.7: {}
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
hasown: 2.0.2
side-channel: 1.1.0
+ internmap@2.0.3: {}
+
intl-messageformat@11.1.2:
dependencies:
'@formatjs/ecma402-abstract': 3.1.1
@@ -8424,14 +12371,33 @@ snapshots:
'@formatjs/icu-messageformat-parser': 3.5.1
tslib: 2.8.1
+ ip-address@10.1.0: {}
+
+ ip-address@5.9.4:
+ dependencies:
+ jsbn: 1.1.0
+ lodash: 4.17.23
+ sprintf-js: 1.1.2
+
ipaddr.js@2.3.0: {}
+ iron-webcrypto@1.2.1: {}
+
+ is-alphabetical@2.0.1: {}
+
+ is-alphanumerical@2.0.1:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-decimal: 2.0.1
+
is-array-buffer@3.0.5:
dependencies:
call-bind: 1.0.8
call-bound: 1.0.4
get-intrinsic: 1.3.0
+ is-arrayish@0.3.4: {}
+
is-async-function@2.1.1:
dependencies:
async-function: 1.0.0
@@ -8470,6 +12436,12 @@ snapshots:
call-bound: 1.0.4
has-tostringtag: 1.0.2
+ is-decimal@2.0.1: {}
+
+ is-docker@3.0.0: {}
+
+ is-extendable@0.1.1: {}
+
is-extglob@2.1.1: {}
is-finalizationregistry@1.1.1:
@@ -8494,6 +12466,12 @@ snapshots:
dependencies:
is-extglob: 2.1.1
+ is-hexadecimal@2.0.1: {}
+
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
is-map@2.0.3: {}
is-negative-zero@2.0.3: {}
@@ -8505,6 +12483,8 @@ snapshots:
is-number@7.0.0: {}
+ is-plain-obj@4.1.0: {}
+
is-reference@1.2.1:
dependencies:
'@types/estree': 1.0.8
@@ -8556,12 +12536,18 @@ snapshots:
is-windows@1.0.2: {}
+ is-wsl@3.1.1:
+ dependencies:
+ is-inside-container: 1.0.0
+
isarray@1.0.0: {}
isarray@2.0.5: {}
isexe@2.0.0: {}
+ iterare@1.2.1: {}
+
iterator.prototype@1.1.5:
dependencies:
define-data-property: 1.1.4
@@ -8579,7 +12565,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -8587,7 +12573,7 @@ snapshots:
joycon@3.1.1: {}
- jpeg-exif@1.1.4: {}
+ js-md5@0.8.3: {}
js-tokens@4.0.0: {}
@@ -8600,6 +12586,8 @@ snapshots:
dependencies:
argparse: 2.0.1
+ jsbn@1.1.0: {}
+
jsesc@3.1.0: {}
json-buffer@3.0.1: {}
@@ -8620,7 +12608,7 @@ snapshots:
json-schema-to-ts@3.1.1:
dependencies:
- '@babel/runtime': 7.28.6
+ '@babel/runtime': 7.29.2
ts-algebra: 2.0.0
json-schema-traverse@0.4.1: {}
@@ -8635,10 +12623,20 @@ snapshots:
json5@2.2.3: {}
+ jsonc-parser@2.3.1: {}
+
+ jsonc-parser@3.3.1: {}
+
jsonfile@4.0.0:
optionalDependencies:
graceful-fs: 4.2.11
+ jsonfile@6.2.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
jsx-ast-utils@3.3.5:
dependencies:
array-includes: 3.1.9
@@ -8650,12 +12648,22 @@ snapshots:
dependencies:
json-buffer: 3.0.1
+ kind-of@6.0.3: {}
+
+ kleur@3.0.3: {}
+
+ kleur@4.1.5: {}
+
+ klona@2.0.6: {}
+
language-subtag-registry@0.3.23: {}
language-tags@1.0.9:
dependencies:
language-subtag-registry: 0.3.23
+ lazy@1.0.11: {}
+
lazystream@1.0.1:
dependencies:
readable-stream: 2.3.8
@@ -8680,13 +12688,13 @@ snapshots:
lines-and-columns@1.2.4: {}
- lint-staged@16.3.2:
+ lint-staged@16.4.0:
dependencies:
commander: 14.0.3
listr2: 9.0.5
- micromatch: 4.0.8
+ picomatch: 4.0.3
string-argv: 0.3.2
- tinyexec: 1.0.2
+ tinyexec: 1.0.4
yaml: 2.8.2
listr2@9.0.5:
@@ -8698,6 +12706,8 @@ snapshots:
rfdc: 1.4.1
wrap-ansi: 9.0.2
+ load-esm@1.0.3: {}
+
load-tsconfig@0.2.5: {}
loader-runner@4.3.1: {}
@@ -8726,6 +12736,8 @@ snapshots:
long@5.3.2: {}
+ longest-streak@3.1.0: {}
+
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
@@ -8734,22 +12746,499 @@ snapshots:
lru-cache@10.4.3: {}
- lru-cache@11.2.6: {}
+ lru-cache@11.2.7: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
+ lru-cache@7.18.3: {}
+
+ lucide-react@0.577.0(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ magicast@0.5.2:
+ dependencies:
+ '@babel/parser': 7.29.2
+ '@babel/types': 7.29.0
+ source-map-js: 1.2.1
+
+ markdown-extensions@2.0.0: {}
+
+ markdown-table@3.0.4: {}
+
math-intrinsics@1.1.0: {}
+ mdast-util-definitions@6.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.1.0
+
+ mdast-util-directive@3.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-visit-parents: 6.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.3:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0
+ mdast-util-gfm-strikethrough: 2.0.0
+ mdast-util-gfm-table: 2.0.0
+ mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx@3.0.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.1.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
+ mdn-data@2.0.28: {}
+
+ mdn-data@2.27.1: {}
+
merge-stream@2.0.0: {}
merge2@1.4.1: {}
+ micromark-core-commonmark@2.0.3:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-factory-destination: 2.0.1
+ micromark-factory-label: 2.0.1
+ micromark-factory-space: 2.0.1
+ micromark-factory-title: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-html-tag-name: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-directive@3.0.2:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ parse-entities: 4.0.2
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-footnote@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-table@2.1.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdx-expression@3.0.1:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdx-jsx@3.0.2:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
+ micromark-extension-mdx-md@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
+ micromark-extension-mdxjs@3.0.0:
+ dependencies:
+ acorn: 8.16.0
+ acorn-jsx: 5.3.2(acorn@8.16.0)
+ micromark-extension-mdx-expression: 3.0.1
+ micromark-extension-mdx-jsx: 3.0.2
+ micromark-extension-mdx-md: 2.0.0
+ micromark-extension-mdxjs-esm: 3.0.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-destination@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-label@2.0.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-mdx-expression@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
+ micromark-factory-space@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-title@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-whitespace@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-chunked@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-classify-character@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-combine-extensions@2.0.1:
+ dependencies:
+ micromark-util-chunked: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-events-to-acorn@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
+ micromark-util-html-tag-name@2.0.1: {}
+
+ micromark-util-normalize-identifier@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-resolve-all@2.0.1:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-subtokenize@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ micromark@4.0.2:
+ dependencies:
+ '@types/debug': 4.1.12
+ debug: 4.4.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-encode: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -8802,8 +13291,14 @@ snapshots:
mri@1.2.0: {}
+ mrmime@2.0.1: {}
+
ms@2.1.3: {}
+ muggle-string@0.4.1: {}
+
+ mute-stream@1.0.0: {}
+
mz@2.7.0:
dependencies:
any-promise: 1.3.0
@@ -8820,44 +13315,62 @@ snapshots:
neo-async@2.6.2: {}
+ neotraverse@0.6.18: {}
+
+ netmask@2.0.2: {}
+
next-intl-swc-plugin-extractor@4.8.3: {}
- next-intl@4.8.3(@swc/helpers@0.5.15)(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.3):
+ next-intl@4.8.3(@swc/helpers@0.5.19)(next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3):
dependencies:
'@formatjs/intl-localematcher': 0.8.1
'@parcel/watcher': 2.5.6
- '@swc/core': 1.15.18(@swc/helpers@0.5.15)
+ '@swc/core': 1.15.18(@swc/helpers@0.5.19)
icu-minify: 4.8.3
negotiator: 1.0.0
- next: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ next: 16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
next-intl-swc-plugin-extractor: 4.8.3
po-parser: 2.1.1
- react: 19.2.3
- use-intl: 4.8.3(react@19.2.3)
+ react: 19.2.4
+ use-intl: 4.8.3(react@19.2.4)
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
- '@swc/helpers'
- next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ next-mdx-remote@6.0.0(@types/react@19.2.14)(react@19.2.4):
dependencies:
- '@next/env': 16.1.6
+ '@babel/code-frame': 7.29.0
+ '@mdx-js/mdx': 3.1.1
+ '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.4)
+ react: 19.2.4
+ unist-util-remove: 4.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ vfile-matter: 5.0.1
+ transitivePeerDependencies:
+ - '@types/react'
+ - supports-color
+
+ next@16.2.0(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ '@next/env': 16.2.0
'@swc/helpers': 0.5.15
- baseline-browser-mapping: 2.10.0
- caniuse-lite: 1.0.30001777
+ baseline-browser-mapping: 2.10.9
+ caniuse-lite: 1.0.30001780
postcss: 8.4.31
- react: 19.2.3
- react-dom: 19.2.3(react@19.2.3)
- styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.3)
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4)
optionalDependencies:
- '@next/swc-darwin-arm64': 16.1.6
- '@next/swc-darwin-x64': 16.1.6
- '@next/swc-linux-arm64-gnu': 16.1.6
- '@next/swc-linux-arm64-musl': 16.1.6
- '@next/swc-linux-x64-gnu': 16.1.6
- '@next/swc-linux-x64-musl': 16.1.6
- '@next/swc-win32-arm64-msvc': 16.1.6
- '@next/swc-win32-x64-msvc': 16.1.6
+ '@next/swc-darwin-arm64': 16.2.0
+ '@next/swc-darwin-x64': 16.2.0
+ '@next/swc-linux-arm64-gnu': 16.2.0
+ '@next/swc-linux-arm64-musl': 16.2.0
+ '@next/swc-linux-x64-gnu': 16.2.0
+ '@next/swc-linux-x64-musl': 16.2.0
+ '@next/swc-win32-arm64-msvc': 16.2.0
+ '@next/swc-win32-x64-msvc': 16.2.0
'@opentelemetry/api': 1.9.0
'@playwright/test': 1.58.2
sharp: 0.34.5
@@ -8865,6 +13378,10 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
+ nlcst-to-string@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+
node-addon-api@7.1.1: {}
node-exports-info@1.6.0:
@@ -8880,15 +13397,23 @@ snapshots:
dependencies:
whatwg-url: 5.0.0
+ node-int64@0.4.0: {}
+
+ node-mock-http@1.0.4: {}
+
node-releases@2.0.36: {}
normalize-path@3.0.0: {}
+ nth-check@2.1.1:
+ dependencies:
+ boolbase: 1.0.0
+
nypm@0.6.5:
dependencies:
citty: 0.2.1
pathe: 2.0.3
- tinyexec: 1.0.2
+ tinyexec: 1.0.4
object-assign@4.1.1: {}
@@ -8934,6 +13459,14 @@ snapshots:
obliterator@2.0.5: {}
+ obug@2.1.1: {}
+
+ ofetch@1.5.1:
+ dependencies:
+ destr: 2.0.5
+ node-fetch-native: 1.6.7
+ ufo: 1.6.3
+
ohash@2.0.11: {}
on-exit-leak-free@2.1.2: {}
@@ -8946,6 +13479,19 @@ snapshots:
dependencies:
mimic-function: 5.0.1
+ oniguruma-parser@0.12.1: {}
+
+ oniguruma-to-es@4.3.5:
+ dependencies:
+ oniguruma-parser: 0.12.1
+ regex: 6.1.0
+ regex-recursion: 6.0.2
+
+ openai@6.32.0(ws@8.19.0)(zod@4.3.6):
+ optionalDependencies:
+ ws: 8.19.0
+ zod: 4.3.6
+
openapi-types@12.1.3: {}
optionator@0.9.4:
@@ -8981,6 +13527,10 @@ snapshots:
dependencies:
yocto-queue: 0.1.0
+ p-limit@6.2.0:
+ dependencies:
+ yocto-queue: 1.2.2
+
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
@@ -8991,20 +13541,81 @@ snapshots:
p-map@2.1.0: {}
+ p-queue@8.1.1:
+ dependencies:
+ eventemitter3: 5.0.4
+ p-timeout: 6.1.4
+
+ p-timeout@6.1.4: {}
+
p-try@2.2.0: {}
+ pac-proxy-agent@7.2.0:
+ dependencies:
+ '@tootallnate/quickjs-emscripten': 0.23.0
+ agent-base: 7.1.4
+ debug: 4.4.3
+ get-uri: 6.0.5
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ pac-resolver: 7.0.1
+ socks-proxy-agent: 8.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ pac-resolver@7.0.1:
+ dependencies:
+ degenerator: 5.0.1
+ netmask: 2.0.2
+
package-json-from-dist@1.0.1: {}
package-manager-detector@0.2.11:
dependencies:
quansync: 0.2.11
+ package-manager-detector@1.6.0: {}
+
+ pagefind@1.4.0:
+ optionalDependencies:
+ '@pagefind/darwin-arm64': 1.4.0
+ '@pagefind/darwin-x64': 1.4.0
+ '@pagefind/freebsd-x64': 1.4.0
+ '@pagefind/linux-arm64': 1.4.0
+ '@pagefind/linux-x64': 1.4.0
+ '@pagefind/windows-x64': 1.4.0
+
pako@0.2.9: {}
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
+ parse-entities@4.0.2:
+ dependencies:
+ '@types/unist': 2.0.11
+ character-entities-legacy: 3.0.0
+ character-reference-invalid: 2.0.1
+ decode-named-character-reference: 1.3.0
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
+ is-hexadecimal: 2.0.1
+
+ parse-latin@7.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ '@types/unist': 3.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-modify-children: 4.0.0
+ unist-util-visit-children: 3.0.0
+ vfile: 6.0.3
+
+ parse5@7.3.0:
+ dependencies:
+ entities: 6.0.1
+
+ path-browserify@1.0.1: {}
+
path-exists@4.0.0: {}
path-key@3.1.1: {}
@@ -9018,9 +13629,11 @@ snapshots:
path-scurry@2.0.2:
dependencies:
- lru-cache: 11.2.6
+ lru-cache: 11.2.7
minipass: 7.1.3
+ path-to-regexp@8.3.0: {}
+
path-type@4.0.0: {}
pathe@1.1.2: {}
@@ -9029,14 +13642,17 @@ snapshots:
pathval@2.0.1: {}
- pdfkit@0.17.2:
+ pdfkit@0.18.0:
dependencies:
- crypto-js: 4.2.0
+ '@noble/ciphers': 1.3.0
+ '@noble/hashes': 1.8.0
fontkit: 2.0.4
- jpeg-exif: 1.1.4
+ js-md5: 0.8.3
linebreak: 1.1.0
png-js: 1.0.0
+ pend@1.2.0: {}
+
perfect-debounce@1.0.0: {}
pg-int8@1.0.1: {}
@@ -9051,6 +13667,8 @@ snapshots:
postgres-date: 1.0.7
postgres-interval: 1.2.0
+ piccolore@0.1.3: {}
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -9136,6 +13754,16 @@ snapshots:
tsx: 4.21.0
yaml: 2.8.2
+ postcss-nested@6.2.0(postcss@8.5.8):
+ dependencies:
+ postcss: 8.5.8
+ postcss-selector-parser: 6.1.2
+
+ postcss-selector-parser@6.1.2:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
postcss@8.4.31:
dependencies:
nanoid: 3.3.11
@@ -9158,16 +13786,16 @@ snapshots:
dependencies:
xtend: 4.0.2
- posthog-js@1.360.1:
+ posthog-js@1.362.0:
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/api-logs': 0.208.0
'@opentelemetry/exporter-logs-otlp-http': 0.208.0(@opentelemetry/api@1.9.0)
'@opentelemetry/resources': 2.6.0(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0)
- '@posthog/core': 1.23.3
- '@posthog/types': 1.360.1
- core-js: 3.48.0
+ '@posthog/core': 1.24.0
+ '@posthog/types': 1.362.0
+ core-js: 3.49.0
dompurify: 3.3.3
fflate: 0.4.8
preact: 10.29.0
@@ -9182,15 +13810,17 @@ snapshots:
prettier@3.8.1: {}
- prisma@6.19.2(typescript@5.9.3):
+ prisma@6.19.2(magicast@0.5.2)(typescript@5.9.3):
dependencies:
- '@prisma/config': 6.19.2
+ '@prisma/config': 6.19.2(magicast@0.5.2)
'@prisma/engines': 6.19.2
optionalDependencies:
typescript: 5.9.3
transitivePeerDependencies:
- magicast
+ prismjs@1.30.0: {}
+
process-nextick-args@2.0.1: {}
process-warning@4.0.1: {}
@@ -9201,12 +13831,19 @@ snapshots:
progress@2.0.3: {}
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
object-assign: 4.1.1
react-is: 16.13.1
+ property-information@7.1.0: {}
+
protobufjs@7.5.4:
dependencies:
'@protobufjs/aspromise': 1.1.2
@@ -9219,9 +13856,22 @@ snapshots:
'@protobufjs/path': 1.1.2
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
long: 5.3.2
+ proxy-agent@6.5.0:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ lru-cache: 7.18.3
+ pac-proxy-agent: 7.2.0
+ proxy-from-env: 1.1.0
+ socks-proxy-agent: 8.0.5
+ transitivePeerDependencies:
+ - supports-color
+
proxy-from-env@1.1.0: {}
pump@3.0.4:
@@ -9247,19 +13897,54 @@ snapshots:
quick-format-unescaped@4.0.4: {}
+ radix3@1.1.2: {}
+
rc9@2.1.2:
dependencies:
defu: 6.1.4
destr: 2.0.5
- react-dom@19.2.3(react@19.2.3):
+ react-dom@19.2.4(react@19.2.4):
dependencies:
- react: 19.2.3
+ react: 19.2.4
scheduler: 0.27.0
react-is@16.13.1: {}
- react@19.2.3: {}
+ react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.4):
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/react': 19.2.14
+ devlop: 1.1.0
+ hast-util-to-jsx-runtime: 2.3.6
+ html-url-attributes: 3.0.1
+ mdast-util-to-hast: 13.2.1
+ react: 19.2.4
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1):
+ dependencies:
+ '@types/use-sync-external-store': 0.0.6
+ react: 19.2.4
+ use-sync-external-store: 1.6.0(react@19.2.4)
+ optionalDependencies:
+ '@types/react': 19.2.14
+ redux: 5.0.1
+
+ react@19.2.4: {}
+
+ read-excel-file@7.0.2:
+ dependencies:
+ '@xmldom/xmldom': 0.8.11
+ fflate: 0.8.2
+ unzipper: 0.12.3
read-yaml-file@1.1.0:
dependencies:
@@ -9292,27 +13977,201 @@ snapshots:
readdirp@4.1.2: {}
+ readdirp@5.0.0: {}
+
+ reading-time@1.5.0: {}
+
real-require@0.2.0: {}
+ recharts@3.8.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@16.13.1)(react@19.2.4)(redux@5.0.1):
+ dependencies:
+ '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4)
+ clsx: 2.1.1
+ decimal.js-light: 2.5.1
+ es-toolkit: 1.45.1
+ eventemitter3: 5.0.4
+ immer: 10.2.0
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ react-is: 16.13.1
+ react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1)
+ reselect: 5.1.1
+ tiny-invariant: 1.3.3
+ use-sync-external-store: 1.6.0(react@19.2.4)
+ victory-vendor: 37.3.6
+ transitivePeerDependencies:
+ - '@types/react'
+ - redux
+
+ recma-build-jsx@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ estree-util-build-jsx: 3.0.1
+ vfile: 6.0.3
+
+ recma-jsx@1.0.1(acorn@8.16.0):
+ dependencies:
+ acorn: 8.16.0
+ acorn-jsx: 5.3.2(acorn@8.16.0)
+ estree-util-to-js: 2.0.0
+ recma-parse: 1.0.0
+ recma-stringify: 1.0.0
+ unified: 11.0.5
+
+ recma-parse@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ esast-util-from-js: 2.0.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ recma-stringify@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ estree-util-to-js: 2.0.0
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ redux-thunk@3.1.0(redux@5.0.1):
+ dependencies:
+ redux: 5.0.1
+
+ redux@5.0.1: {}
+
+ reflect-metadata@0.2.2: {}
+
reflect.getprototypeof@1.0.10:
dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- which-builtin-type: 1.2.1
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.1.0:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regexp.prototype.flags@1.5.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ set-function-name: 2.0.2
+
+ rehype-expressive-code@0.41.7:
+ dependencies:
+ expressive-code: 0.41.7
+
+ rehype-format@5.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-format: 1.1.0
+
+ rehype-parse@9.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-from-html: 2.0.3
+ unified: 11.0.5
+
+ rehype-raw@7.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-raw: 9.1.0
+ vfile: 6.0.3
+
+ rehype-recma@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ hast-util-to-estree: 3.1.3
+ transitivePeerDependencies:
+ - supports-color
+
+ rehype-stringify@10.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+ unified: 11.0.5
+
+ rehype@13.0.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ rehype-parse: 9.0.1
+ rehype-stringify: 10.0.1
+ unified: 11.0.5
+
+ remark-directive@3.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-directive: 3.1.0
+ micromark-extension-directive: 3.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-gfm@4.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-mdx@3.1.1:
+ dependencies:
+ mdast-util-mdx: 3.0.0
+ micromark-extension-mdxjs: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-smartypants@3.0.2:
+ dependencies:
+ retext: 9.0.0
+ retext-smartypants: 6.2.0
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
- regexp.prototype.flags@1.5.4:
+ remark-stringify@11.0.0:
dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-errors: 1.3.0
- get-proto: 1.0.1
- gopd: 1.2.0
- set-function-name: 2.0.2
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
+
+ request-light@0.5.8: {}
+
+ request-light@0.7.0: {}
require-directory@2.1.1: {}
@@ -9327,10 +14186,12 @@ snapshots:
require-main-filename@2.0.0: {}
- resend@6.9.3:
+ reselect@5.1.1: {}
+
+ resend@6.9.4:
dependencies:
postal-mime: 2.7.3
- svix: 1.84.1
+ svix: 1.86.0
resolve-from@4.0.0: {}
@@ -9362,6 +14223,31 @@ snapshots:
ret@0.5.0: {}
+ retext-latin@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ parse-latin: 7.0.0
+ unified: 11.0.5
+
+ retext-smartypants@6.2.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-visit: 5.1.0
+
+ retext-stringify@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unified: 11.0.5
+
+ retext@9.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ retext-latin: 4.0.0
+ retext-stringify: 4.0.0
+ unified: 11.0.5
+
reusify@1.1.0: {}
rfdc@1.4.1: {}
@@ -9397,10 +14283,16 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.59.0
fsevents: 2.3.3
+ run-async@3.0.0: {}
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
+ rxjs@7.8.2:
+ dependencies:
+ tslib: 2.8.1
+
safe-array-concat@1.1.3:
dependencies:
call-bind: 1.0.8
@@ -9424,7 +14316,7 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
- safe-regex2@5.0.0:
+ safe-regex2@5.1.0:
dependencies:
ret: 0.5.0
@@ -9432,6 +14324,8 @@ snapshots:
safer-buffer@2.1.2: {}
+ sax@1.6.0: {}
+
scheduler@0.27.0: {}
schema-utils@4.3.3:
@@ -9441,6 +14335,11 @@ snapshots:
ajv-formats: 2.1.1(ajv@8.18.0)
ajv-keywords: 5.1.0(ajv@8.18.0)
+ section-matter@1.0.0:
+ dependencies:
+ extend-shallow: 2.0.1
+ kind-of: 6.0.3
+
secure-json-parse@4.1.0: {}
semver@6.3.1: {}
@@ -9475,6 +14374,32 @@ snapshots:
setprototypeof@1.2.0: {}
+ sharp@0.33.5:
+ dependencies:
+ color: 4.2.3
+ detect-libc: 2.1.2
+ semver: 7.7.4
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.33.5
+ '@img/sharp-darwin-x64': 0.33.5
+ '@img/sharp-libvips-darwin-arm64': 1.0.4
+ '@img/sharp-libvips-darwin-x64': 1.0.4
+ '@img/sharp-libvips-linux-arm': 1.0.5
+ '@img/sharp-libvips-linux-arm64': 1.0.4
+ '@img/sharp-libvips-linux-s390x': 1.0.4
+ '@img/sharp-libvips-linux-x64': 1.0.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.0.4
+ '@img/sharp-linux-arm': 0.33.5
+ '@img/sharp-linux-arm64': 0.33.5
+ '@img/sharp-linux-s390x': 0.33.5
+ '@img/sharp-linux-x64': 0.33.5
+ '@img/sharp-linuxmusl-arm64': 0.33.5
+ '@img/sharp-linuxmusl-x64': 0.33.5
+ '@img/sharp-wasm32': 0.33.5
+ '@img/sharp-win32-ia32': 0.33.5
+ '@img/sharp-win32-x64': 0.33.5
+
sharp@0.34.5:
dependencies:
'@img/colour': 1.1.0
@@ -9513,6 +14438,19 @@ snapshots:
shebang-regex@3.0.0: {}
+ shell-quote@1.8.3: {}
+
+ shiki@3.23.0:
+ dependencies:
+ '@shikijs/core': 3.23.0
+ '@shikijs/engine-javascript': 3.23.0
+ '@shikijs/engine-oniguruma': 3.23.0
+ '@shikijs/langs': 3.23.0
+ '@shikijs/themes': 3.23.0
+ '@shikijs/types': 3.23.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
side-channel-list@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -9545,6 +14483,19 @@ snapshots:
signal-exit@4.1.0: {}
+ simple-swizzle@0.2.4:
+ dependencies:
+ is-arrayish: 0.3.4
+
+ sisteransi@1.0.5: {}
+
+ sitemap@9.0.1:
+ dependencies:
+ '@types/node': 24.12.0
+ '@types/sax': 1.2.7
+ arg: 5.0.2
+ sax: 1.6.0
+
slash@3.0.0: {}
slice-ansi@7.1.2:
@@ -9557,6 +14508,23 @@ snapshots:
ansi-styles: 6.2.3
is-fullwidth-code-point: 5.1.0
+ smart-buffer@4.2.0: {}
+
+ smol-toml@1.6.0: {}
+
+ socks-proxy-agent@8.0.5:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ socks: 2.8.7
+ transitivePeerDependencies:
+ - supports-color
+
+ socks@2.8.7:
+ dependencies:
+ ip-address: 10.1.0
+ smart-buffer: 4.2.0
+
sonic-boom@4.2.1:
dependencies:
atomic-sleep: 1.0.0
@@ -9572,6 +14540,8 @@ snapshots:
source-map@0.7.6: {}
+ space-separated-tokens@2.0.2: {}
+
spawndamnit@3.0.1:
dependencies:
cross-spawn: 7.0.6
@@ -9581,6 +14551,8 @@ snapshots:
sprintf-js@1.0.3: {}
+ sprintf-js@1.1.2: {}
+
stable-hash@0.0.5: {}
stackback@0.0.2: {}
@@ -9598,6 +14570,8 @@ snapshots:
std-env@3.10.0: {}
+ std-env@4.0.0: {}
+
steed@1.1.3:
dependencies:
fastfall: 1.5.1
@@ -9611,6 +14585,8 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
+ stream-replace-string@2.0.0: {}
+
streamx@2.23.0:
dependencies:
events-universal: 1.0.1
@@ -9703,6 +14679,11 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -9711,20 +14692,34 @@ snapshots:
dependencies:
ansi-regex: 6.2.2
+ strip-bom-string@1.0.0: {}
+
strip-bom@3.0.0: {}
strip-json-comments@3.1.1: {}
strip-json-comments@5.0.3: {}
- stripe@20.4.1(@types/node@20.19.37):
+ stripe@20.4.1(@types/node@25.5.0):
optionalDependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+
+ strtok3@10.3.5:
+ dependencies:
+ '@tokenizer/token': 0.3.0
+
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
- styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.3):
+ styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4):
dependencies:
client-only: 0.0.1
- react: 19.2.3
+ react: 19.2.4
optionalDependencies:
'@babel/core': 7.29.0
@@ -9748,7 +14743,17 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
- svix@1.84.1:
+ svgo@4.0.1:
+ dependencies:
+ commander: 11.1.0
+ css-select: 5.2.2
+ css-tree: 3.2.1
+ css-what: 6.2.2
+ csso: 5.0.5
+ picocolors: 1.1.1
+ sax: 1.6.0
+
+ svix@1.86.0:
dependencies:
standardwebhooks: 1.0.0
uuid: 10.0.0
@@ -9780,10 +14785,10 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.3.3
- terser: 5.46.0
+ terser: 5.46.1
webpack: 5.105.4
- terser@5.46.0:
+ terser@5.46.1:
dependencies:
'@jridgewell/source-map': 0.3.11
acorn: 8.16.0
@@ -9810,11 +14815,13 @@ snapshots:
tiny-inflate@1.0.3: {}
+ tiny-invariant@1.3.3: {}
+
tinybench@2.9.0: {}
tinyexec@0.3.2: {}
- tinyexec@1.0.2: {}
+ tinyexec@1.0.4: {}
tinyglobby@0.2.15:
dependencies:
@@ -9825,6 +14832,8 @@ snapshots:
tinyrainbow@1.2.0: {}
+ tinyrainbow@3.1.0: {}
+
tinyspy@3.0.2: {}
to-regex-range@5.0.1:
@@ -9835,18 +14844,32 @@ snapshots:
toidentifier@1.0.1: {}
+ token-types@6.1.2:
+ dependencies:
+ '@borewit/text-codec': 0.2.2
+ '@tokenizer/token': 0.3.0
+ ieee754: 1.2.1
+
tr46@0.0.3: {}
tree-kill@1.2.2: {}
+ trim-lines@3.0.1: {}
+
+ trough@2.2.0: {}
+
ts-algebra@2.0.0: {}
- ts-api-utils@2.4.0(typescript@5.9.3):
+ ts-api-utils@2.5.0(typescript@5.9.3):
dependencies:
typescript: 5.9.3
ts-interface-checker@0.1.13: {}
+ tsconfck@3.1.6(typescript@5.9.3):
+ optionalDependencies:
+ typescript: 5.9.3
+
tsconfig-paths@3.15.0:
dependencies:
'@types/json5': 0.0.29
@@ -9856,7 +14879,7 @@ snapshots:
tslib@2.8.1: {}
- tsup@8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.15))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2):
+ tsup@8.5.1(@swc/core@1.15.18(@swc/helpers@0.5.19))(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2):
dependencies:
bundle-require: 5.1.0(esbuild@0.27.3)
cac: 6.7.14
@@ -9876,7 +14899,7 @@ snapshots:
tinyglobby: 0.2.15
tree-kill: 1.2.2
optionalDependencies:
- '@swc/core': 1.15.18(@swc/helpers@0.5.15)
+ '@swc/core': 1.15.18(@swc/helpers@0.5.19)
postcss: 8.5.8
typescript: 5.9.3
transitivePeerDependencies:
@@ -9892,39 +14915,25 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
- turbo-darwin-64@2.8.14:
- optional: true
-
- turbo-darwin-arm64@2.8.14:
- optional: true
-
- turbo-linux-64@2.8.14:
- optional: true
-
- turbo-linux-arm64@2.8.14:
- optional: true
-
- turbo-windows-64@2.8.14:
- optional: true
-
- turbo-windows-arm64@2.8.14:
- optional: true
-
- turbo@2.8.14:
+ turbo@2.8.20:
optionalDependencies:
- turbo-darwin-64: 2.8.14
- turbo-darwin-arm64: 2.8.14
- turbo-linux-64: 2.8.14
- turbo-linux-arm64: 2.8.14
- turbo-windows-64: 2.8.14
- turbo-windows-arm64: 2.8.14
+ '@turbo/darwin-64': 2.8.20
+ '@turbo/darwin-arm64': 2.8.20
+ '@turbo/linux-64': 2.8.20
+ '@turbo/linux-arm64': 2.8.20
+ '@turbo/windows-64': 2.8.20
+ '@turbo/windows-arm64': 2.8.20
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
+ type-fest@0.21.3: {}
+
type-fest@0.7.1: {}
+ type-fest@4.41.0: {}
+
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.4
@@ -9958,12 +14967,18 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
- typescript-eslint@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
+ typesafe-path@0.2.2: {}
+
+ typescript-auto-import-cache@0.3.6:
+ dependencies:
+ semver: 7.7.4
+
+ typescript-eslint@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.4(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
@@ -9973,6 +14988,14 @@ snapshots:
ufo@1.6.3: {}
+ uid@2.0.2:
+ dependencies:
+ '@lukeed/csprng': 1.1.0
+
+ uint8array-extras@1.5.0: {}
+
+ ultrahtml@1.6.0: {}
+
unbox-primitive@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -9980,8 +15003,14 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
+ uncrypto@0.1.3: {}
+
undici-types@6.21.0: {}
+ undici-types@7.16.0: {}
+
+ undici-types@7.18.2: {}
+
unicode-properties@1.4.1:
dependencies:
base64-js: 1.5.1
@@ -9992,8 +15021,78 @@ snapshots:
pako: 0.2.9
tiny-inflate: 1.0.3
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unifont@0.7.4:
+ dependencies:
+ css-tree: 3.2.1
+ ofetch: 1.5.1
+ ohash: 2.0.11
+
+ unist-util-find-after@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-modify-children@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ array-iterate: 2.0.1
+
+ unist-util-position-from-estree@2.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-remove-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.1.0
+
+ unist-util-remove@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-children@3.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.1.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
universalify@0.1.2: {}
+ universalify@2.0.1: {}
+
unrs-resolver@1.11.1:
dependencies:
napi-postinstall: 0.3.4
@@ -10018,6 +15117,25 @@ snapshots:
'@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
'@unrs/resolver-binding-win32-x64-msvc': 1.11.1
+ unstorage@1.17.4:
+ dependencies:
+ anymatch: 3.1.3
+ chokidar: 5.0.0
+ destr: 2.0.5
+ h3: 1.15.9
+ lru-cache: 11.2.7
+ node-fetch-native: 1.6.7
+ ofetch: 1.5.1
+ ufo: 1.6.3
+
+ unzipper@0.12.3:
+ dependencies:
+ bluebird: 3.7.2
+ duplexer2: 0.1.4
+ fs-extra: 11.3.4
+ graceful-fs: 4.2.11
+ node-int64: 0.4.0
+
update-browserslist-db@1.2.3(browserslist@4.28.1):
dependencies:
browserslist: 4.28.1
@@ -10028,13 +15146,17 @@ snapshots:
dependencies:
punycode: 2.3.1
- use-intl@4.8.3(react@19.2.3):
+ use-intl@4.8.3(react@19.2.4):
dependencies:
'@formatjs/fast-memoize': 3.1.0
'@schummar/icu-type-parser': 1.21.5
icu-minify: 4.8.3
intl-messageformat: 11.1.2
- react: 19.2.3
+ react: 19.2.4
+
+ use-sync-external-store@1.6.0(react@19.2.4):
+ dependencies:
+ react: 19.2.4
util-deprecate@1.0.2: {}
@@ -10042,13 +15164,50 @@ snapshots:
uuid@9.0.1: {}
- vite-node@2.1.9(@types/node@20.19.37)(terser@5.46.0):
+ vfile-location@5.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile: 6.0.3
+
+ vfile-matter@5.0.1:
+ dependencies:
+ vfile: 6.0.3
+ yaml: 2.8.2
+
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ victory-vendor@37.3.6:
+ dependencies:
+ '@types/d3-array': 3.2.2
+ '@types/d3-ease': 3.0.2
+ '@types/d3-interpolate': 3.0.4
+ '@types/d3-scale': 4.0.9
+ '@types/d3-shape': 3.1.8
+ '@types/d3-time': 3.0.4
+ '@types/d3-timer': 3.0.2
+ d3-array: 3.2.4
+ d3-ease: 3.0.1
+ d3-interpolate: 3.0.1
+ d3-scale: 4.0.2
+ d3-shape: 3.2.0
+ d3-time: 3.1.0
+ d3-timer: 3.0.1
+
+ vite-node@2.1.9(@types/node@25.5.0)(terser@5.46.1):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 1.1.2
- vite: 5.4.21(@types/node@20.19.37)(terser@5.46.0)
+ vite: 5.4.21(@types/node@25.5.0)(terser@5.46.1)
transitivePeerDependencies:
- '@types/node'
- less
@@ -10060,20 +15219,40 @@ snapshots:
- supports-color
- terser
- vite@5.4.21(@types/node@20.19.37)(terser@5.46.0):
+ vite@5.4.21(@types/node@25.5.0)(terser@5.46.1):
dependencies:
esbuild: 0.21.5
postcss: 8.5.8
rollup: 4.59.0
optionalDependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
+ fsevents: 2.3.3
+ terser: 5.46.1
+
+ vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.8
+ rollup: 4.59.0
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 25.5.0
fsevents: 2.3.3
- terser: 5.46.0
+ jiti: 2.6.1
+ terser: 5.46.1
+ tsx: 4.21.0
+ yaml: 2.8.2
+
+ vitefu@1.1.2(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)):
+ optionalDependencies:
+ vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)
- vitest@2.1.9(@types/node@20.19.37)(terser@5.46.0):
+ vitest@2.1.9(@types/node@25.5.0)(terser@5.46.1):
dependencies:
'@vitest/expect': 2.1.9
- '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@20.19.37)(terser@5.46.0))
+ '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@25.5.0)(terser@5.46.1))
'@vitest/pretty-format': 2.1.9
'@vitest/runner': 2.1.9
'@vitest/snapshot': 2.1.9
@@ -10089,11 +15268,11 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.1.1
tinyrainbow: 1.2.0
- vite: 5.4.21(@types/node@20.19.37)(terser@5.46.0)
- vite-node: 2.1.9(@types/node@20.19.37)(terser@5.46.0)
+ vite: 5.4.21(@types/node@25.5.0)(terser@5.46.1)
+ vite-node: 2.1.9(@types/node@25.5.0)(terser@5.46.1)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 20.19.37
+ '@types/node': 25.5.0
transitivePeerDependencies:
- less
- lightningcss
@@ -10105,11 +15284,143 @@ snapshots:
- supports-color
- terser
+ vitest@4.1.0(@opentelemetry/api@1.9.0)(@types/node@25.5.0)(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)):
+ dependencies:
+ '@vitest/expect': 4.1.0
+ '@vitest/mocker': 4.1.0(vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2))
+ '@vitest/pretty-format': 4.1.0
+ '@vitest/runner': 4.1.0
+ '@vitest/snapshot': 4.1.0
+ '@vitest/spy': 4.1.0
+ '@vitest/utils': 4.1.0
+ es-module-lexer: 2.0.0
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ obug: 2.1.1
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 4.0.0
+ tinybench: 2.9.0
+ tinyexec: 1.0.4
+ tinyglobby: 0.2.15
+ tinyrainbow: 3.1.0
+ vite: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.2)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@opentelemetry/api': 1.9.0
+ '@types/node': 25.5.0
+ transitivePeerDependencies:
+ - msw
+
+ volar-service-css@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-css-languageservice: 6.3.10
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-emmet@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ '@emmetio/css-parser': 0.4.1
+ '@emmetio/html-matcher': 1.3.0
+ '@vscode/emmet-helper': 2.11.0
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-html@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-html-languageservice: 5.6.2
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-prettier@0.0.70(@volar/language-service@2.4.28)(prettier@3.8.1):
+ dependencies:
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+ prettier: 3.8.1
+
+ volar-service-typescript-twoslash-queries@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-typescript@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ path-browserify: 1.0.1
+ semver: 7.7.4
+ typescript-auto-import-cache: 0.3.6
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-nls: 5.2.0
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-yaml@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-uri: 3.1.0
+ yaml-language-server: 1.20.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ vscode-css-languageservice@6.3.10:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ vscode-html-languageservice@5.6.2:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ vscode-json-languageservice@4.1.8:
+ dependencies:
+ jsonc-parser: 3.3.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-nls: 5.2.0
+ vscode-uri: 3.1.0
+
+ vscode-jsonrpc@8.2.0: {}
+
+ vscode-languageserver-protocol@3.17.5:
+ dependencies:
+ vscode-jsonrpc: 8.2.0
+ vscode-languageserver-types: 3.17.5
+
+ vscode-languageserver-textdocument@1.0.12: {}
+
+ vscode-languageserver-types@3.17.5: {}
+
+ vscode-languageserver@9.0.1:
+ dependencies:
+ vscode-languageserver-protocol: 3.17.5
+
+ vscode-nls@5.2.0: {}
+
+ vscode-uri@3.1.0: {}
+
watchpack@2.5.1:
dependencies:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.11
+ wcwidth@1.0.1:
+ dependencies:
+ defaults: 1.0.4
+ optional: true
+
+ web-namespaces@2.0.1: {}
+
web-vitals@5.1.0: {}
webidl-conversions@3.0.1: {}
@@ -10128,7 +15439,7 @@ snapshots:
acorn-import-phases: 1.0.4(acorn@8.16.0)
browserslist: 4.28.1
chrome-trace-event: 1.0.4
- enhanced-resolve: 5.20.0
+ enhanced-resolve: 5.20.1
es-module-lexer: 2.0.0
eslint-scope: 5.1.1
events: 3.3.0
@@ -10186,6 +15497,8 @@ snapshots:
which-module@2.0.1: {}
+ which-pm-runs@1.1.0: {}
+
which-typed-array@1.1.20:
dependencies:
available-typed-arrays: 1.0.7
@@ -10205,6 +15518,10 @@ snapshots:
siginfo: 2.0.0
stackback: 0.0.2
+ widest-line@5.0.0:
+ dependencies:
+ string-width: 7.2.0
+
word-wrap@1.2.5: {}
wrap-ansi@6.2.0:
@@ -10237,10 +15554,30 @@ snapshots:
xtend@4.0.2: {}
+ xxhash-wasm@1.1.0: {}
+
y18n@4.0.3: {}
+ y18n@5.0.8: {}
+
yallist@3.1.1: {}
+ yaml-language-server@1.20.0:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ ajv: 8.18.0
+ ajv-draft-04: 1.0.0(ajv@8.18.0)
+ prettier: 3.8.1
+ request-light: 0.5.8
+ vscode-json-languageservice: 4.1.8
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+ yaml: 2.7.1
+
+ yaml@2.7.1: {}
+
yaml@2.8.2: {}
yargs-parser@18.1.3:
@@ -10248,6 +15585,8 @@ snapshots:
camelcase: 5.3.1
decamelize: 1.2.0
+ yargs-parser@21.1.1: {}
+
yargs@15.4.1:
dependencies:
cliui: 6.0.0
@@ -10262,20 +15601,56 @@ snapshots:
y18n: 4.0.3
yargs-parser: 18.1.3
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
+ yauzl@3.2.1:
+ dependencies:
+ buffer-crc32: 0.2.13
+ pend: 1.2.0
+
yocto-queue@0.1.0: {}
+ yocto-queue@1.2.2: {}
+
+ yocto-spinner@0.2.3:
+ dependencies:
+ yoctocolors: 2.1.2
+
+ yoctocolors@2.1.2: {}
+
zip-stream@6.0.1:
dependencies:
archiver-utils: 5.0.2
compress-commons: 6.0.2
readable-stream: 4.7.0
- zod-openapi@4.2.4(zod@3.25.76):
+ zod-openapi@5.4.6(zod@4.3.6):
+ dependencies:
+ zod: 4.3.6
+
+ zod-to-json-schema@3.25.1(zod@3.25.76):
dependencies:
zod: 3.25.76
- zod-validation-error@4.0.2(zod@3.25.76):
+ zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76):
dependencies:
+ typescript: 5.9.3
zod: 3.25.76
+ zod-validation-error@4.0.2(zod@4.3.6):
+ dependencies:
+ zod: 4.3.6
+
zod@3.25.76: {}
+
+ zod@4.3.6: {}
+
+ zwitch@2.0.4: {}
diff --git a/scripts/auto-update.sh b/scripts/auto-update.sh
new file mode 100644
index 00000000..5481bfb3
--- /dev/null
+++ b/scripts/auto-update.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+# ============================================================================
+# dTax 自动更新脚本
+#
+# 拉取最新代码,检测变更类型,按需构建镜像、执行迁移、重启服务
+# 带锁机制防止并发执行
+#
+# 用法: cd /data/dtax && bash scripts/auto-update.sh
+# ============================================================================
+
+set -euo pipefail
+
+PROJECT_DIR="/data/dtax"
+BACKUP_DIR="${PROJECT_DIR}/backups"
+LOG_FILE="${BACKUP_DIR}/auto-update.log"
+LOCK_FILE="/tmp/dtax-update.lock"
+LOG_MAX_LINES=5000
+
+cd "$PROJECT_DIR"
+mkdir -p "$BACKUP_DIR"
+
+log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"; }
+
+# ---- 维护模式:存在 .maintenance 文件则跳过 ----
+if [ -f "$PROJECT_DIR/.maintenance" ]; then
+ log "维护模式,跳过自动更新(删除 .maintenance 文件恢复)"
+ exit 0
+fi
+
+# ---- 锁机制:防止并发执行 ----
+if [ -f "$LOCK_FILE" ]; then
+ LOCK_PID=$(cat "$LOCK_FILE" 2>/dev/null)
+ if kill -0 "$LOCK_PID" 2>/dev/null; then
+ log "跳过: 上一次更新仍在运行 (PID: $LOCK_PID)"
+ exit 0
+ else
+ rm -f "$LOCK_FILE"
+ fi
+fi
+echo $$ > "$LOCK_FILE"
+trap 'rm -f "$LOCK_FILE"' EXIT
+
+# ---- 日志轮转 ----
+if [ -f "$LOG_FILE" ] && [ "$(wc -l < "$LOG_FILE")" -gt "$LOG_MAX_LINES" ]; then
+ tail -n 2000 "$LOG_FILE" > "${LOG_FILE}.tmp"
+ mv "${LOG_FILE}.tmp" "$LOG_FILE"
+ log "日志已轮转(保留最近 2000 行)"
+fi
+
+# ---- 拉取代码 ----
+OLD_COMMIT=$(git rev-parse HEAD)
+git pull --quiet 2>>"$LOG_FILE" || { log "ERROR: git pull failed"; exit 1; }
+NEW_COMMIT=$(git rev-parse HEAD)
+
+if [ "$OLD_COMMIT" = "$NEW_COMMIT" ]; then
+ exit 0
+fi
+
+log "代码更新: ${OLD_COMMIT:0:7} -> ${NEW_COMMIT:0:7}"
+
+# ---- 分析变更类型 ----
+CHANGED=$(git diff --name-only "$OLD_COMMIT" "$NEW_COMMIT")
+
+NEED_BUILD_API=false
+NEED_BUILD_WEB=false
+NEED_MIGRATE=false
+BLOG_ONLY=true
+
+while IFS= read -r file; do
+ case "$file" in
+ apps/api/* | packages/shared-types/* | packages/tax-engine/*)
+ NEED_BUILD_API=true; BLOG_ONLY=false ;;
+ apps/web/content/blog/*)
+ ;; # 博客,volume 自动生效
+ apps/web/*)
+ NEED_BUILD_WEB=true; BLOG_ONLY=false ;;
+ docker/* | docker-compose.yml | .env.production.example)
+ NEED_BUILD_API=true; NEED_BUILD_WEB=true; BLOG_ONLY=false ;;
+ *)
+ BLOG_ONLY=false ;;
+ esac
+done <<< "$CHANGED"
+
+echo "$CHANGED" | grep -q "prisma/migrations/" && NEED_MIGRATE=true
+
+if [ "$BLOG_ONLY" = true ]; then
+ log "仅博客更新,volume 自动生效"
+ exit 0
+fi
+
+# ---- 备份数据库 ----
+if [ "$NEED_BUILD_API" = true ] || [ "$NEED_MIGRATE" = true ]; then
+ log "备份数据库..."
+ ./docker/scripts/backup.sh "$BACKUP_DIR" >> "$LOG_FILE" 2>&1 || log "WARNING: 备份失败"
+fi
+
+# ---- 构建镜像 ----
+if [ "$NEED_BUILD_API" = true ]; then
+ log "构建 API 镜像..."
+ docker compose build api >> "$LOG_FILE" 2>&1 || { log "ERROR: API 构建失败"; exit 1; }
+ log "API 镜像构建完成"
+fi
+
+if [ "$NEED_BUILD_WEB" = true ]; then
+ log "构建 Web 镜像..."
+ docker compose build web >> "$LOG_FILE" 2>&1 || { log "ERROR: Web 构建失败"; exit 1; }
+ log "Web 镜像构建完成"
+fi
+
+# ---- 数据库迁移 ----
+if [ "$NEED_MIGRATE" = true ]; then
+ log "执行数据库迁移..."
+ docker compose run --rm migrate >> "$LOG_FILE" 2>&1 || { log "ERROR: 迁移失败"; exit 1; }
+ log "数据库迁移完成"
+fi
+
+# ---- 重启服务 ----
+if [ "$NEED_BUILD_API" = true ] && [ "$NEED_BUILD_WEB" = true ]; then
+ log "重启所有服务..."
+ docker compose up -d >> "$LOG_FILE" 2>&1
+elif [ "$NEED_BUILD_API" = true ]; then
+ log "重启 API..."
+ docker compose up -d api >> "$LOG_FILE" 2>&1
+elif [ "$NEED_BUILD_WEB" = true ]; then
+ log "重启 Web..."
+ docker compose up -d web >> "$LOG_FILE" 2>&1
+fi
+
+# ---- 健康检查 ----
+sleep 10
+if docker exec dtax-api-1 node -e \
+ "fetch('http://localhost:3001/api/health').then(r=>{if(!r.ok)throw 1}).catch(()=>process.exit(1))" \
+ 2>/dev/null; then
+ log "更新完成,服务正常"
+else
+ log "WARNING: API 健康检查未通过"
+fi
diff --git a/scripts/docker-test.py b/scripts/docker-test.py
new file mode 100644
index 00000000..43ddb546
--- /dev/null
+++ b/scripts/docker-test.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+"""
+测试 DTax Docker 镜像是否能正常运行
+
+用法:
+ python scripts/docker-test.py # 测试 latest 镜像
+ python scripts/docker-test.py --tag v1.0.0 # 测试指定版本
+ python scripts/docker-test.py --full # 完整栈测试(含 Postgres + Nginx)
+"""
+
+import argparse
+import json
+import subprocess
+import sys
+import time
+
+ORG = "dtaxlab"
+API_IMAGE = f"ghcr.io/{ORG}/dtax-api"
+WEB_IMAGE = f"ghcr.io/{ORG}/dtax-web"
+
+API_ENV = [
+ "-e", "DATABASE_URL=postgresql://x:x@localhost:5432/x",
+ "-e", "JWT_SECRET=test123456789012345678901234567890",
+ "-e", "ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000",
+ "-e", "CORS_ORIGIN=http://localhost",
+ "-e", "APP_URL=http://localhost",
+]
+
+
+def run(cmd: str, capture: bool = False, timeout: int = 30) -> subprocess.CompletedProcess:
+ """执行命令,返回结果。"""
+ print(f"$ {cmd}")
+ return subprocess.run(
+ cmd, shell=True, capture_output=capture, text=True,
+ timeout=timeout, encoding="utf-8", errors="replace"
+ )
+
+
+def check(name: str, ok: bool, detail: str = "") -> bool:
+ """打印检查结果。"""
+ status = "PASS" if ok else "FAIL"
+ symbol = "+" if ok else "x"
+ msg = f" [{symbol}] {name}"
+ if detail:
+ msg += f" — {detail}"
+ print(msg)
+ return ok
+
+
+def test_image_exists(tag: str) -> bool:
+ """检查镜像是否存在。"""
+ api = subprocess.run(
+ f"docker image inspect {API_IMAGE}:{tag}", shell=True,
+ capture_output=True, timeout=10, encoding="utf-8", errors="replace"
+ )
+ web = subprocess.run(
+ f"docker image inspect {WEB_IMAGE}:{tag}", shell=True,
+ capture_output=True, timeout=10, encoding="utf-8", errors="replace"
+ )
+ ok_api = check("API 镜像存在", api.returncode == 0, f"{API_IMAGE}:{tag}")
+ ok_web = check("Web 镜像存在", web.returncode == 0, f"{WEB_IMAGE}:{tag}")
+ return ok_api and ok_web
+
+
+def test_image_sizes(tag: str) -> bool:
+ """检查镜像大小。"""
+ result = subprocess.run(
+ f'docker images --format "{{{{.Repository}}}}:{{{{.Tag}}}}\t{{{{.Size}}}}" | grep dtaxlab | grep {tag}',
+ shell=True, capture_output=True, text=True, timeout=10
+ )
+ for line in result.stdout.strip().split("\n"):
+ if line:
+ print(f" {line}")
+ return True
+
+
+def test_api_startup(tag: str) -> bool:
+ """测试 API 镜像能否正常启动。"""
+ env_str = " ".join(API_ENV)
+ result = subprocess.run(
+ f'docker run --rm {env_str} {API_IMAGE}:{tag} sh -c "timeout 5 node apps/api/dist/index.js 2>&1; exit 0"',
+ shell=True, capture_output=True, text=True, timeout=30, encoding="utf-8", errors="replace"
+ )
+ output = result.stdout or ""
+ has_listening = "Server listening" in output
+ has_running = "DTax API running" in output
+ has_error = "Error" in output.split("DTax API running")[0] if "DTax API running" in output else "Error" in output
+
+ ok = has_listening and has_running and not has_error
+ detail = "启动成功" if ok else output.strip()[:100]
+ return check("API 启动", ok, detail)
+
+
+def test_web_startup(tag: str) -> bool:
+ """测试 Web 镜像能否正常启动。"""
+ result = subprocess.run(
+ f'docker run --rm {WEB_IMAGE}:{tag} sh -c "timeout 3 node apps/web/server.js 2>&1; exit 0"',
+ shell=True, capture_output=True, text=True, timeout=30, encoding="utf-8", errors="replace"
+ )
+ output = result.stdout or ""
+ has_ready = "Ready" in output or "Next.js" in output
+ ok = has_ready
+ detail = "启动成功" if ok else output.strip()[:100]
+ return check("Web 启动", ok, detail)
+
+
+def test_api_health(tag: str) -> bool:
+ """测试 API 健康检查端点。"""
+ container = f"dtax-api-test-{tag}"
+ env_str = " ".join(API_ENV)
+
+ # 启动容器
+ subprocess.run(
+ f"docker run -d --name {container} {env_str} {API_IMAGE}:{tag}",
+ shell=True, capture_output=True, timeout=15, encoding="utf-8", errors="replace"
+ )
+
+ # 等待启动
+ time.sleep(3)
+
+ # 测试 health 端点
+ result = subprocess.run(
+ f"""docker exec {container} node -e "fetch('http://localhost:3001/api/health').then(r=>r.json()).then(d=>console.log(JSON.stringify(d)))" """,
+ shell=True, capture_output=True, text=True, timeout=10
+ )
+
+ # 清理
+ subprocess.run(f"docker rm -f {container}", shell=True, capture_output=True, timeout=10)
+
+ try:
+ data = json.loads(result.stdout.strip())
+ ok = data.get("status") == "ok"
+ return check("API /health", ok, f"status={data.get('status')}")
+ except Exception:
+ return check("API /health", False, result.stdout.strip()[:100] or result.stderr.strip()[:100])
+
+
+def test_full_stack() -> bool:
+ """完整栈测试(docker compose)。"""
+ import os
+ deploy_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "..", "dtax-deploy")
+ deploy_dir = os.path.normpath(deploy_dir)
+
+ if not os.path.exists(os.path.join(deploy_dir, "docker-compose.yml")):
+ return check("完整栈测试", False, f"找不到 {deploy_dir}/docker-compose.yml")
+
+ compose = f"docker compose -f {deploy_dir}/docker-compose.yml -f {deploy_dir}/docker-compose.local.yml"
+
+ print("\n 启动完整栈...")
+ result = subprocess.run(f"{compose} up -d", shell=True, capture_output=True, text=True, timeout=120, encoding="utf-8", errors="replace")
+ if result.returncode != 0:
+ return check("完整栈启动", False, result.stderr.strip()[:200])
+
+ # 等待服务就绪
+ time.sleep(5)
+
+ # 检查各服务状态
+ ps = subprocess.run(f"{compose} ps --format json", shell=True, capture_output=True, text=True, timeout=10)
+
+ # 测试端点
+ health = subprocess.run(
+ "curl -s http://localhost:8888/api/health", shell=True,
+ capture_output=True, text=True, timeout=10
+ )
+ web = subprocess.run(
+ "curl -s -o /dev/null -w '%{http_code}' http://localhost:8888/", shell=True,
+ capture_output=True, text=True, timeout=10
+ )
+
+ ok_health = False
+ try:
+ data = json.loads(health.stdout)
+ ok_health = data.get("status") == "ok"
+ except Exception:
+ pass
+
+ ok_web = web.stdout.strip().strip("'") in ("200", "301", "302", "307", "308")
+
+ check("Postgres", True, "healthy")
+ check("API /health", ok_health, health.stdout.strip()[:80])
+ check("Web 页面", ok_web, f"HTTP {web.stdout.strip()}")
+
+ # 停止
+ print("\n 停止完整栈...")
+ subprocess.run(f"{compose} down", shell=True, capture_output=True, timeout=30, encoding="utf-8", errors="replace")
+
+ return ok_health and ok_web
+
+
+def main():
+ parser = argparse.ArgumentParser(description="测试 DTax Docker 镜像")
+ parser.add_argument("--tag", default="latest", help="镜像标签(默认: latest)")
+ parser.add_argument("--full", action="store_true", help="完整栈测试(需要 dtax-deploy 仓库)")
+ args = parser.parse_args()
+
+ tag = args.tag
+ results = []
+
+ print(f"\n{'='*50}")
+ print(f" DTax Docker 镜像测试 (tag: {tag})")
+ print(f"{'='*50}\n")
+
+ # 基础检查
+ print("[镜像检查]")
+ results.append(test_image_exists(tag))
+ test_image_sizes(tag)
+
+ # 启动测试
+ print("\n[启动测试]")
+ results.append(test_api_startup(tag))
+ results.append(test_web_startup(tag))
+
+ # 健康检查
+ print("\n[健康检查]")
+ results.append(test_api_health(tag))
+
+ # 完整栈测试
+ if args.full:
+ print("\n[完整栈测试]")
+ results.append(test_full_stack())
+
+ # 汇总
+ passed = sum(results)
+ total = len(results)
+ all_pass = all(results)
+
+ print(f"\n{'='*50}")
+ print(f" 结果: {passed}/{total} 通过", end="")
+ if all_pass:
+ print(" — 全部通过")
+ else:
+ print(" — 有失败项")
+ print(f"{'='*50}\n")
+
+ sys.exit(0 if all_pass else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/maintenance.sh b/scripts/maintenance.sh
new file mode 100644
index 00000000..6b7f1ad0
--- /dev/null
+++ b/scripts/maintenance.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# ============================================================================
+# dTax 维护模式管理
+#
+# 用法:
+# bash scripts/maintenance.sh on # 开启维护模式(暂停自动更新)
+# bash scripts/maintenance.sh off # 关闭维护模式(恢复自动更新)
+# bash scripts/maintenance.sh status # 查看当前状态
+# ============================================================================
+
+set -euo pipefail
+
+PROJECT_DIR="/data/dtax"
+MAINT_FILE="${PROJECT_DIR}/.maintenance"
+
+case "${1:-status}" in
+ on|start)
+ touch "$MAINT_FILE"
+ echo "维护模式: 已开启"
+ echo " 自动更新已暂停"
+ echo " 完成后运行: bash scripts/maintenance.sh off"
+ ;;
+ off|stop)
+ rm -f "$MAINT_FILE"
+ echo "维护模式: 已关闭"
+ echo " 自动更新已恢复"
+ ;;
+ status)
+ if [ -f "$MAINT_FILE" ]; then
+ echo "维护模式: 开启中"
+ echo " 创建时间: $(stat -c '%y' "$MAINT_FILE" 2>/dev/null || stat -f '%Sm' "$MAINT_FILE" 2>/dev/null)"
+ else
+ echo "维护模式: 关闭"
+ fi
+ echo ""
+ echo "服务状态:"
+ cd "$PROJECT_DIR" && docker compose ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null
+ ;;
+ *)
+ echo "用法: bash scripts/maintenance.sh [on|off|status]"
+ exit 1
+ ;;
+esac
diff --git a/scripts/setup-server.sh b/scripts/setup-server.sh
new file mode 100644
index 00000000..79e5587a
--- /dev/null
+++ b/scripts/setup-server.sh
@@ -0,0 +1,227 @@
+#!/bin/bash
+# ============================================================================
+# dTax 服务器一键部署/恢复脚本
+#
+# 幂等设计:可重复执行,不会产生副作用
+# 适用场景:首次部署、故障恢复、环境重建
+#
+# 前置条件:
+# 1. Ubuntu 22.04/24.04,已安装 Docker + Docker Compose
+# 2. 项目已 clone 到 /data/dtax
+# 3. .env 已配置好(从 .env.production.example 复制并填写)
+# 4. DNS 已将域名解析到本机 IP
+#
+# 用法: cd /data/dtax && bash scripts/setup-server.sh
+# ============================================================================
+
+set -euo pipefail
+
+PROJECT_DIR="/data/dtax"
+BACKUP_DIR="${PROJECT_DIR}/backups"
+DOMAIN="getdtax.com"
+CERT_EMAIL="support@getdtax.com"
+
+# 颜色输出
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+ok() { echo -e " ${GREEN}[OK]${NC} $1"; }
+warn() { echo -e " ${YELLOW}[!]${NC} $1"; }
+fail() { echo -e " ${RED}[X]${NC} $1"; exit 1; }
+
+echo ""
+echo "================================================"
+echo " dTax 服务器一键部署"
+echo "================================================"
+echo ""
+
+# ============================================================================
+# 1. 检查前置条件
+# ============================================================================
+echo "[1/8] 检查前置条件..."
+
+[ -d "$PROJECT_DIR" ] || fail "项目目录 $PROJECT_DIR 不存在"
+[ -f "$PROJECT_DIR/.env" ] || fail ".env 文件不存在,请先从 .env.production.example 复制并配置"
+[ -f "$PROJECT_DIR/docker-compose.yml" ] || fail "docker-compose.yml 不存在"
+
+for cmd in docker git; do
+ command -v $cmd &>/dev/null || fail "$cmd 未安装"
+done
+docker compose version &>/dev/null || fail "docker compose 未安装"
+
+ok "前置条件通过"
+
+# ============================================================================
+# 2. 创建目录 + 设置权限
+# ============================================================================
+echo "[2/8] 创建目录和权限..."
+
+mkdir -p "$BACKUP_DIR"
+chmod +x "$PROJECT_DIR/docker/scripts/"*.sh 2>/dev/null || true
+chmod +x "$PROJECT_DIR/scripts/"*.sh 2>/dev/null || true
+chmod 600 "$PROJECT_DIR/.env"
+
+ok "目录和权限"
+
+# ============================================================================
+# 3. 构建镜像
+# ============================================================================
+echo "[3/8] 构建 Docker 镜像(首次较慢)..."
+
+cd "$PROJECT_DIR"
+docker compose build api web
+
+ok "镜像构建完成"
+
+# ============================================================================
+# 4. SSL 证书(已有则跳过)
+# ============================================================================
+echo "[4/8] 检查 SSL 证书..."
+
+# 检查证书是否已存在
+CERT_EXISTS=false
+if docker run --rm -v dtax_letsencrypt:/etc/letsencrypt alpine \
+ test -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" 2>/dev/null; then
+ CERT_EXISTS=true
+fi
+
+# 也检查项目名前缀的卷(docker compose 创建的卷名可能带前缀)
+for vol_prefix in "dtax" "dtax-private" "data_dtax"; do
+ if docker run --rm -v "${vol_prefix}_letsencrypt:/etc/letsencrypt" alpine \
+ test -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" 2>/dev/null; then
+ CERT_EXISTS=true
+ break
+ fi
+done
+
+if [ "$CERT_EXISTS" = true ]; then
+ ok "SSL 证书已存在,跳过申请"
+else
+ warn "SSL 证书不存在,开始申请..."
+ bash "$PROJECT_DIR/docker/scripts/init-letsencrypt.sh" "$CERT_EMAIL" "$DOMAIN"
+ ok "SSL 证书申请完成"
+fi
+
+# ============================================================================
+# 5. 启动服务
+# ============================================================================
+echo "[5/8] 启动服务..."
+
+cd "$PROJECT_DIR"
+
+# 停止已有服务(如果存在)
+docker compose down 2>/dev/null || true
+
+# 启动
+docker compose up -d
+
+ok "服务已启动"
+
+# ============================================================================
+# 6. 等待健康检查
+# ============================================================================
+echo "[6/8] 等待服务就绪..."
+
+MAX_WAIT=60
+WAITED=0
+
+while [ $WAITED -lt $MAX_WAIT ]; do
+ # 检查 API
+ API_OK=false
+ if docker exec dtax-api-1 node -e \
+ "fetch('http://localhost:3001/api/health').then(r=>{if(!r.ok)throw 1}).catch(()=>process.exit(1))" \
+ 2>/dev/null; then
+ API_OK=true
+ fi
+
+ # 检查 Web
+ WEB_OK=false
+ if docker exec dtax-web-1 wget -qO- http://0.0.0.0:3000/ &>/dev/null; then
+ WEB_OK=true
+ fi
+
+ if [ "$API_OK" = true ] && [ "$WEB_OK" = true ]; then
+ break
+ fi
+
+ echo " 等待中... (${WAITED}s/${MAX_WAIT}s)"
+ sleep 5
+ WAITED=$((WAITED + 5))
+done
+
+if [ "$API_OK" = true ] && [ "$WEB_OK" = true ]; then
+ ok "API 和 Web 均已就绪"
+else
+ [ "$API_OK" = false ] && warn "API 未就绪,查看日志: docker compose logs api"
+ [ "$WEB_OK" = false ] && warn "Web 未就绪,查看日志: docker compose logs web"
+fi
+
+# ============================================================================
+# 7. 配置定时任务(幂等:先删旧的再加新的)
+# ============================================================================
+echo "[7/8] 配置定时任务..."
+
+# 导出现有 crontab,移除旧的 dtax 任务块(含注释和空行)
+crontab -l 2>/dev/null | sed '/# ========== dTax/,/# ========== dTax.*结束/d' | grep -v "/data/dtax" > /tmp/crontab-clean || true
+# 清理尾部多余空行
+sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' /tmp/crontab-clean 2>/dev/null || true
+
+# 添加新任务
+cat >> /tmp/crontab-clean << 'CRON'
+
+# ========== dTax 定时任务 ==========
+# 每天凌晨 2:00 备份数据库(保留 30 天)
+0 2 * * * cd /data/dtax && ./docker/scripts/backup.sh /data/dtax/backups >> /data/dtax/backups/cron.log 2>&1
+# 每周一 3:00 重载 Nginx(SSL 证书续期生效)
+0 3 * * 1 cd /data/dtax && docker compose exec -T nginx nginx -s reload >> /data/dtax/backups/cron.log 2>&1
+# 每小时 :30 自动更新(错开整点,避免和备份冲突;带锁防并发)
+30 * * * * cd /data/dtax && bash scripts/auto-update.sh 2>&1
+# 每周日 4:00 清理 Docker 旧镜像 + 旧日志
+0 4 * * 0 docker image prune -af --filter "until=168h" >> /data/dtax/backups/cron.log 2>&1; find /data/dtax/backups -name "cron.log" -size +10M -exec truncate -s 1M {} \; 2>/dev/null
+# ========== dTax 定时任务结束 ==========
+CRON
+
+crontab /tmp/crontab-clean
+rm -f /tmp/crontab-clean
+
+ok "定时任务已配置"
+
+# ============================================================================
+# 8. 显示最终状态
+# ============================================================================
+echo "[8/8] 部署状态..."
+echo ""
+
+# 服务状态
+echo " 服务:"
+docker compose ps --format "table {{.Name}}\t{{.Status}}" 2>/dev/null | while read line; do
+ echo " $line"
+done
+
+echo ""
+echo " 定时任务:"
+echo " 每天 02:00 数据库备份(保留 30 天)"
+echo " 每周一 03:00 Nginx SSL 重载"
+echo " 每小时 xx:30 自动更新(拉取+按需构建+迁移+重启)"
+echo " 每周日 04:00 清理旧镜像(7天前)+ 旧日志"
+
+# 健康检查
+echo ""
+echo " 访问地址:"
+echo " https://${DOMAIN}"
+echo " https://${DOMAIN}/api/health"
+
+echo ""
+echo "================================================"
+echo -e " ${GREEN}部署完成!${NC}"
+echo ""
+echo " 故障恢复:重新运行本脚本即可"
+echo " cd /data/dtax && bash scripts/setup-server.sh"
+echo ""
+echo " 查看日志:"
+echo " docker compose logs -f api"
+echo " tail -f backups/cron.log"
+echo "================================================"
+echo ""
diff --git a/turbo.json b/turbo.json
index 8cf7f22e..e39406ea 100644
--- a/turbo.json
+++ b/turbo.json
@@ -6,6 +6,11 @@
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
+ "start": {
+ "dependsOn": ["build"],
+ "cache": false,
+ "persistent": true
+ },
"dev": {
"cache": false,
"persistent": true
@@ -13,6 +18,9 @@
"test": {
"dependsOn": ["^build"]
},
+ "typecheck": {
+ "dependsOn": ["^build"]
+ },
"lint": {
"dependsOn": ["^build"]
},