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 +

dTax

+

+ El único motor completo de impuestos cripto en TypeScript disponible en npm +

+

+ CI + License + npm + Stars +

+

+ 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 +

dTax

+

+ npm で利用できる唯一の完全な TypeScript 暗号資産税務エンジン +

+

+ CI + License + npm + Stars +

+

+ 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 +

dTax

+

+ npm에서 유일한 완전한 TypeScript 암호화폐 세금 엔진 +

+

+ CI + License + npm + Stars +

+

+ 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 +

dTax

The only complete TypeScript crypto tax engine on npm

@@ -9,11 +10,14 @@ npm Stars

+

+ 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 +

dTax

+

+ O único motor completo de impostos sobre criptomoedas em TypeScript no npm +

+

+ CI + License + npm + Stars +

+

+ 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 +

dTax

+

+ npm 上唯一完整的 TypeScript 加密貨幣稅務引擎 +

+

+ CI + License + npm + Stars +

+

+ 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 +

dTax

+

+ npm 上唯一完整的 TypeScript 加密货币税务引擎 +

+

+ CI + License + npm + Stars +

+

+ 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) | + + + +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** + + + +```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`) | + + + +3. **Start services** + + + + 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** + + + +```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`) | + + + +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** + + + +```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`) | + + + +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** + + + +```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` 実行前に設定必須) | + + + +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` 실행 전에 설정 필수) | + + + +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` 之前设置) | + + + +3. **启动服务** + + + + 此命令会启动 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: `