From b0da76f8157e26a7a0d048cf04efd6c27198f0f7 Mon Sep 17 00:00:00 2001 From: cynox-66 Date: Fri, 26 Jun 2026 18:37:01 +0530 Subject: [PATCH 1/7] feat(sprint-3): implement connector resilience, strategy chain, discovery engine, and fixture tests --- .dependency-cruiser.js | 48 + .editorconfig | 12 + .github/workflows/ci.yml | 50 + .github/workflows/release.yml | 46 + .gitignore | 9 + .lintstagedrc.json | 4 + .prettierrc.json | 11 + PROJECT_CHARTER.md | 206 + PROJECT_CONTEXT.md | 388 + apps/extension/manifest.json | 19 + apps/extension/package.json | 25 + apps/extension/public/index.html | 12 + apps/extension/src/background/index.ts | 118 + apps/extension/src/content/index.ts | 81 + apps/extension/src/popup/index.tsx | 78 + apps/extension/tsconfig.json | 10 + apps/extension/vite.config.ts | 8 + commitlint.config.js | 3 + connectors/instagram/package.json | 20 + connectors/instagram/src/discovery-engine.ts | 99 + connectors/instagram/src/fingerprinter.ts | 30 + connectors/instagram/src/index.ts | 55 + connectors/instagram/src/parser.ts | 101 + connectors/instagram/src/strategies.ts | 186 + connectors/instagram/src/strategy-chain.ts | 51 + connectors/instagram/tests/connector.test.ts | 99 + .../fixtures/carousel-post.expected.json | 93 + .../tests/fixtures/carousel-post.html | 29 + .../tests/fixtures/reel-post.expected.json | 33 + .../instagram/tests/fixtures/reel-post.html | 23 + .../fixtures/single-image-post.expected.json | 28 + .../tests/fixtures/single-image-post.html | 22 + connectors/instagram/tsconfig.json | 8 + connectors/instagram/vitest.config.ts | 8 + docs/architecture/dependency-graph.md | 98 + docs/architecture/domain-model.md | 110 + docs/rfc/.gitkeep | 0 docs/verification/sprint-2.md | 29 + eslint.config.mjs | 13 +- package.json | 36 + packages/shared/package.json | 9 + packages/shared/src/feature-flags.ts | 34 + packages/shared/src/index.ts | 3 + packages/shared/src/logger.ts | 47 + packages/shared/src/metrics-collector.ts | 67 + packages/shared/tsconfig.json | 8 + packages/storage/package.json | 10 + packages/storage/src/index.ts | 1 + packages/storage/src/memory-storage.ts | 36 + packages/storage/tsconfig.json | 8 + packages/types/package.json | 6 + packages/types/src/connector/fingerprint.ts | 16 + packages/types/src/connector/index.ts | 5 + packages/types/src/connector/metrics.ts | 24 + packages/types/src/connector/parser.ts | 29 + packages/types/src/connector/pipeline.ts | 36 + packages/types/src/connector/strategy.ts | 30 + pnpm-lock.yaml | 8194 +++++++++++++++++ pnpm-workspace.yaml | 4 + tsconfig.base.json | 18 + tsconfig.json | 15 + turbo.json | 22 + 62 files changed, 10918 insertions(+), 3 deletions(-) create mode 100644 .dependency-cruiser.js create mode 100644 .editorconfig create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .lintstagedrc.json create mode 100644 .prettierrc.json create mode 100644 PROJECT_CHARTER.md create mode 100644 PROJECT_CONTEXT.md create mode 100644 apps/extension/manifest.json create mode 100644 apps/extension/package.json create mode 100644 apps/extension/public/index.html create mode 100644 apps/extension/tsconfig.json create mode 100644 apps/extension/vite.config.ts create mode 100644 commitlint.config.js create mode 100644 connectors/instagram/package.json create mode 100644 connectors/instagram/src/discovery-engine.ts create mode 100644 connectors/instagram/src/fingerprinter.ts create mode 100644 connectors/instagram/src/index.ts create mode 100644 connectors/instagram/src/parser.ts create mode 100644 connectors/instagram/src/strategies.ts create mode 100644 connectors/instagram/src/strategy-chain.ts create mode 100644 connectors/instagram/tests/connector.test.ts create mode 100644 connectors/instagram/tests/fixtures/carousel-post.expected.json create mode 100644 connectors/instagram/tests/fixtures/carousel-post.html create mode 100644 connectors/instagram/tests/fixtures/reel-post.expected.json create mode 100644 connectors/instagram/tests/fixtures/reel-post.html create mode 100644 connectors/instagram/tests/fixtures/single-image-post.expected.json create mode 100644 connectors/instagram/tests/fixtures/single-image-post.html create mode 100644 connectors/instagram/tsconfig.json create mode 100644 connectors/instagram/vitest.config.ts create mode 100644 docs/architecture/dependency-graph.md create mode 100644 docs/architecture/domain-model.md create mode 100644 docs/rfc/.gitkeep create mode 100644 docs/verification/sprint-2.md create mode 100644 package.json create mode 100644 packages/shared/package.json create mode 100644 packages/shared/src/feature-flags.ts create mode 100644 packages/shared/src/logger.ts create mode 100644 packages/shared/src/metrics-collector.ts create mode 100644 packages/shared/tsconfig.json create mode 100644 packages/storage/package.json create mode 100644 packages/storage/src/memory-storage.ts create mode 100644 packages/storage/tsconfig.json create mode 100644 packages/types/package.json create mode 100644 packages/types/src/connector/fingerprint.ts create mode 100644 packages/types/src/connector/metrics.ts create mode 100644 packages/types/src/connector/parser.ts create mode 100644 packages/types/src/connector/pipeline.ts create mode 100644 packages/types/src/connector/strategy.ts create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tsconfig.base.json create mode 100644 tsconfig.json create mode 100644 turbo.json diff --git a/.dependency-cruiser.js b/.dependency-cruiser.js new file mode 100644 index 0000000..46395ff --- /dev/null +++ b/.dependency-cruiser.js @@ -0,0 +1,48 @@ +/** @type {import('dependency-cruiser').IConfiguration} */ +module.exports = { + forbidden: [ + { + name: 'no-circular', + severity: 'error', + comment: 'Warns on circular dependencies.', + from: {}, + to: { circular: true } + }, + { + name: 'connectors-cannot-import-connectors', + severity: 'error', + comment: 'A connector can only import types, shared, and utils. It cannot import other connectors.', + from: { path: '^connectors/([^/]+)/' }, + to: { path: '^connectors/([^/]+)/', pathNot: '^connectors/$1/' } + }, + { + name: 'no-app-dependencies', + severity: 'error', + comment: 'No package or connector may import from apps.', + from: { pathNot: '^apps/' }, + to: { path: '^apps/' } + }, + { + name: 'primitives-no-imports', + severity: 'error', + comment: 'packages/types is Layer 0. It cannot import anything from within the monorepo.', + from: { path: '^packages/types/' }, + to: { path: '^(packages|connectors|apps)/', pathNot: '^packages/types/' } + }, + { + name: 'core-utilities-isolation', + severity: 'error', + comment: 'Layer 1 (shared, utils) can only import from Layer 0 (types).', + from: { path: '^packages/(shared|utils)/' }, + to: { path: '^(packages|connectors|apps)/', pathNot: '^packages/(types|shared|utils)/' } + } + ], + options: { + doNotFollow: { + path: 'node_modules' + }, + tsConfig: { + fileName: 'tsconfig.base.json' + } + } +}; diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4bd3bd8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cb00400 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: CI + +on: + pull_request: + branches: [main] + +jobs: + validate: + name: Validate, Lint, and Build + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v3 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Lint Commits + run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} + + - name: Enforce Architecture (Dependency Cruiser) + run: pnpm run depcruise + + - name: Format Check + run: pnpm run format:check + + - name: Lint + run: pnpm run lint + + - name: Typecheck + run: pnpm run typecheck + + - name: Test + run: pnpm run test + + - name: Build + run: pnpm run build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..47c70ec --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: Release + +on: + push: + branches: + - main + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Version and Publish + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup pnpm + uses: pnpm/action-setup@v3 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Build All Packages + run: pnpm run build + + - name: Create Release Pull Request or Publish + id: changesets + uses: changesets/action@v1 + with: + publish: pnpm run publish-packages + commit: 'chore(release): version packages' + title: 'chore(release): version packages' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..306f915 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +node_modules/ +dist/ +lib/ +.turbo/ +coverage/ +.env +.env.local +*.log +.DS_Store diff --git a/.lintstagedrc.json b/.lintstagedrc.json new file mode 100644 index 0000000..76f7ce9 --- /dev/null +++ b/.lintstagedrc.json @@ -0,0 +1,4 @@ +{ + "*.{ts,tsx}": ["eslint --fix", "prettier --write"], + "*.{md,json,yaml,yml}": ["prettier --write"] +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..6789c6c --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,11 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/PROJECT_CHARTER.md b/PROJECT_CHARTER.md new file mode 100644 index 0000000..0712399 --- /dev/null +++ b/PROJECT_CHARTER.md @@ -0,0 +1,206 @@ +# Knowledge Extractor Project Charter + +**Version:** 1.0 + +--- + +# Purpose + +Knowledge Extractor exists to solve a simple but increasingly common problem: + +People consume thousands of pieces of valuable information across the internet, but very little of it becomes searchable, reusable knowledge. + +Most content is trapped inside social media platforms, videos, screenshots, PDFs, articles, and other proprietary interfaces. + +Knowledge Extractor transforms that fragmented information into structured, portable, searchable knowledge that belongs to the user. + +--- + +# Vision + +Build a modular knowledge ingestion platform capable of collecting, extracting, and normalizing information from any supported source into a unified knowledge representation. + +The long-term vision is to make personal knowledge portable, searchable, AI-ready, and independent of any individual platform. + +Instagram is only the first connector. + +The platform should eventually support any information source where users legitimately have access to content. + +--- + +# Target Users + +Knowledge Extractor is designed for people who actively collect information for learning or work. + +Examples include: + +- Engineers +- Students +- Researchers +- Technical writers +- Designers +- Entrepreneurs +- Content creators +- Lifelong learners + +Anyone who saves information today and struggles to find it later should benefit from this project. + +--- + +# Problems We Intend to Solve + +Knowledge Extractor aims to solve problems such as: + +- Saved information becoming impossible to search. +- Valuable ideas hidden inside images or videos. +- Platform lock-in preventing data portability. +- Repeatedly rediscovering the same content. +- Fragmented knowledge spread across multiple services. +- Difficulty preparing saved content for AI workflows or personal knowledge systems. + +The project focuses on extraction, normalization, and portability rather than content consumption. + +--- + +# Problems We Will Not Solve + +Knowledge Extractor will not: + +- Automate social media engagement. +- Like, comment, or message on behalf of users. +- Circumvent authentication or access restrictions. +- Scrape information users are not authorized to access. +- Attempt to replace official APIs where they are available and appropriate. +- Become another note-taking application. + +The project extracts knowledge. It does not attempt to become a complete productivity platform. + +--- + +# Core Principles + +## User Ownership + +Extracted knowledge belongs to the user. + +The platform should make it easy to export, migrate, and reuse extracted data without vendor lock-in. + +--- + +## Connector Independence + +Every connector should be isolated. + +Platform-specific logic must never leak into shared packages. + +Adding a new connector should require minimal changes outside that connector. + +--- + +## AI Independence + +AI enrichment is optional. + +Extraction must function without AI. + +Users should be free to choose any downstream AI workflow or model. + +--- + +## Modularity + +Every subsystem should be independently replaceable. + +Storage providers. + +OCR engines. + +Export formats. + +Connectors. + +AI pipelines. + +No implementation should assume a single permanent technology choice. + +--- + +## Transparency + +Extraction pipelines should be deterministic, inspectable, and understandable. + +Hidden transformations should be avoided whenever possible. + +--- + +# Success Criteria + +The project succeeds if it can: + +- Reliably discover user content. +- Extract structured information. +- Recover text from media when appropriate. +- Normalize data into a consistent schema. +- Export portable formats. +- Support multiple independent connectors. +- Remain maintainable as new platforms are added. + +Success is measured by engineering quality, extensibility, correctness, and usefulness—not by the number of supported platforms. + +--- + +# Long-Term Direction + +Knowledge Extractor should evolve into a universal knowledge ingestion engine. + +Every supported source should follow the same lifecycle: + +Discover + +↓ + +Extract + +↓ + +Normalize + +↓ + +Store + +↓ + +Export + +↓ + +(Optional) AI Enrichment + +↓ + +User-Owned Knowledge + +This architecture allows future support for new platforms without redesigning the core system. + +--- + +# Definition of Done + +A feature is considered complete only when: + +- It follows the architectural contracts. +- It is tested. +- It is documented. +- It does not introduce unnecessary coupling. +- It improves the platform without compromising future extensibility. + +Implementation quality is valued over implementation speed. + +--- + +# Guiding Principle + +Knowledge should outlive the platforms that originally contained it. + +Knowledge Extractor exists to make that possible. diff --git a/PROJECT_CONTEXT.md b/PROJECT_CONTEXT.md new file mode 100644 index 0000000..1bb2869 --- /dev/null +++ b/PROJECT_CONTEXT.md @@ -0,0 +1,388 @@ +# Knowledge Extractor — Project Context + +Version: 0.1.0 + +Status: Active Development + +--- + +# Mission + +Knowledge Extractor is a modular knowledge ingestion platform. + +The project is NOT an Instagram scraper. + +Instagram is only the first connector. + +The long-term objective is to build an extensible platform capable of extracting structured knowledge from multiple information sources and transforming it into a searchable personal knowledge base. + +Future connectors include: + +- Instagram +- Reddit +- X (Twitter) +- LinkedIn +- YouTube +- PDFs +- Web Articles +- Additional connectors as required + +--- + +# Core Philosophy + +Separate extraction from processing. + +Separate platform logic from connector logic. + +Separate knowledge extraction from AI enrichment. + +Every subsystem should be replaceable without affecting unrelated parts of the architecture. + +--- + +# Primary Objectives + +The platform should: + +- Discover content +- Extract structured information +- Download media +- Perform OCR +- Normalize extracted information +- Store extracted knowledge +- Export structured datasets +- Support downstream AI enrichment + +The extension is responsible only for collection. + +AI processing happens outside the browser. + +--- + +# Non Goals + +The project is NOT intended to: + +- Automate social media interactions +- Perform engagement +- Send messages +- Like posts +- Follow users +- Circumvent authentication +- Replace official APIs where they exist + +The system operates only on content that the authenticated user already has access to. + +--- + +# High Level Architecture + +User + +↓ + +Extension UI + +↓ + +Background Worker + +↓ + +Connector + +↓ + +Extraction Engine + +↓ + +Storage Engine + +↓ + +Export Engine + +↓ + +AI Pipeline (External) + +↓ + +Knowledge Base + +--- + +# Connector Philosophy + +Every source is implemented as an independent connector. + +A connector owns: + +- navigation +- selectors +- extraction logic +- normalization rules +- source-specific models + +A connector must never contain: + +- storage logic +- OCR implementation +- exporter logic +- AI logic + +The connector only knows how to transform a source into a generic extracted document. + +--- + +# Shared Packages + +packages/types + +Contains only interfaces and shared models. + +packages/shared + +Shared utilities. + +Configuration. + +Logging. + +Constants. + +Errors. + +packages/extractor + +Extraction pipeline. + +Validation. + +Normalization. + +packages/storage + +Persistence layer. + +IndexedDB. + +Future storage providers. + +packages/exporters + +JSON + +Markdown + +CSV + +SQLite + +Future exporters. + +packages/ocr + +OCR abstraction. + +Image preprocessing. + +OCR providers. + +packages/ai + +External AI integration. + +Prompt builders. + +Knowledge transformation. + +--- + +# Architectural Rules + +Rule 1 + +Instagram-specific code never leaves connectors/instagram. + +Rule 2 + +No package may depend on apps/. + +Rule 3 + +Shared packages must not import connectors. + +Rule 4 + +All communication should happen through interfaces. + +Rule 5 + +Avoid circular dependencies. + +Rule 6 + +Prefer composition over inheritance. + +Rule 7 + +Every new subsystem must be independently testable. + +Rule 8 + +No business logic inside the popup UI. + +--- + +# Development Principles + +Every feature follows: + +Research + +↓ + +Architecture + +↓ + +Implementation + +↓ + +Review + +↓ + +Testing + +↓ + +Documentation + +↓ + +Commit + +Never skip architectural reasoning. + +Never implement directly without understanding dependencies. + +--- + +# Current Development Stage + +Sprint 0 + +Goal: + +Build the engineering platform. + +Current priorities: + +- monorepo setup +- build tooling +- TypeScript configuration +- shared interfaces +- extension bootstrap +- message passing +- project infrastructure + +No extraction logic should be implemented until the platform is stable. + +--- + +# Future Milestones + +M0 + +Development Platform + +M1 + +Instagram Discovery + +M2 + +Metadata Extraction + +M3 + +Media Extraction + +M4 + +OCR + +M5 + +Export System + +M6 + +Incremental Sync + +M7 + +AI Enrichment + +M8 + +Additional Connectors + +--- + +# Long-Term Vision + +Knowledge Extractor should evolve into a universal knowledge ingestion platform. + +The same extraction pipeline should support: + +Instagram + +↓ + +Reddit + +↓ + +LinkedIn + +↓ + +X + +↓ + +YouTube + +↓ + +PDF + +↓ + +Articles + +↓ + +Unified Knowledge Representation + +↓ + +Search + +↓ + +AI + +↓ + +Personal Knowledge Base + +No architectural decision should make future connectors significantly harder to implement. + +Every implementation should optimize for maintainability, extensibility, and long-term engineering quality over short-term convenience. diff --git a/apps/extension/manifest.json b/apps/extension/manifest.json new file mode 100644 index 0000000..80c2620 --- /dev/null +++ b/apps/extension/manifest.json @@ -0,0 +1,19 @@ +{ + "manifest_version": 3, + "name": "Knowledge Extractor", + "version": "0.1.0", + "action": { + "default_popup": "public/index.html" + }, + "background": { + "service_worker": "src/background/index.ts", + "type": "module" + }, + "content_scripts": [ + { + "matches": ["*://*.instagram.com/*"], + "js": ["src/content/index.ts"] + } + ], + "permissions": ["activeTab", "scripting"] +} diff --git a/apps/extension/package.json b/apps/extension/package.json new file mode 100644 index 0000000..a9eae4e --- /dev/null +++ b/apps/extension/package.json @@ -0,0 +1,25 @@ +{ + "name": "@knowledge-extractor/extension", + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "dependencies": { + "@knowledge-extractor/types": "workspace:*", + "@knowledge-extractor/shared": "workspace:*", + "@knowledge-extractor/storage": "workspace:*", + "@knowledge-extractor/connector-instagram": "workspace:*", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@crxjs/vite-plugin": "^2.0.0-beta.23", + "@types/chrome": "^0.0.268", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "vite": "^5.3.1" + } +} diff --git a/apps/extension/public/index.html b/apps/extension/public/index.html new file mode 100644 index 0000000..156144d --- /dev/null +++ b/apps/extension/public/index.html @@ -0,0 +1,12 @@ + + + + + + Extractor Popup + + +
+ + + diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index e69de29..aa6b610 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -0,0 +1,118 @@ +/** + * Background Worker — Pipeline Orchestrator + * + * Receives discovery batches from the Content Script, runs normalization + * through the InstagramConnector, persists to InMemoryStorage, and emits + * domain events to the Popup UI. + * + * This worker is completely ignorant of the Instagram DOM. + */ +import { Logger, featureFlags, FeatureFlag, MetricsCollector } from '@knowledge-extractor/shared'; +import { InMemoryStorage } from '@knowledge-extractor/storage'; +import { InstagramConnector } from '@knowledge-extractor/connector-instagram'; +import { IDiscoveredResource } from '@knowledge-extractor/types'; + +const logger = new Logger('BackgroundWorker'); +const storage = new InMemoryStorage(); +const connector = new InstagramConnector(); +const metrics = new MetricsCollector(); + +// ---- Helpers ---------------------------------------------------------------- +function emitEvent(stage: string, data: unknown): void { + chrome.runtime + .sendMessage({ action: 'SYSTEM_STATUS', data: { stage, payload: data } }) + .catch(() => {}); +} + +// ---- Message Dispatcher ----------------------------------------------------- +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.action === 'START_PIPELINE') { + handleStartPipeline().then(sendResponse); + return true; + } + + if (message.action === 'RESOURCES_DISCOVERED') { + handleDiscoveryBatch(message.data).catch((err) => logger.error('Discovery batch error', err)); + return false; + } +}); + +// ---- Pipeline stages -------------------------------------------------------- +async function handleStartPipeline(): Promise<{ success: boolean }> { + metrics.reset(); + const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); + if (!tabs[0]?.id) { + logger.error('No active tab'); + return { success: false }; + } + + try { + await chrome.tabs.sendMessage(tabs[0].id, { action: 'RUN_PIPELINE' }); + emitEvent('PIPELINE_STARTED', { tabId: tabs[0].id }); + return { success: true }; + } catch (err) { + logger.error('Failed to reach content script', err); + return { success: false }; + } +} + +async function handleDiscoveryBatch( + batch: Array<{ resource: IDiscoveredResource; fingerprint: string }>, +): Promise { + if (!featureFlags.isEnabled(FeatureFlag.ENABLE_EXTRACTION)) { + logger.warn('Extraction disabled by feature flag'); + batch.forEach(() => metrics.recordSkipped()); + return; + } + + emitEvent('DISCOVERY_BATCH', { count: batch.length }); + + for (const { resource } of batch) { + const extractStart = Date.now(); + + try { + // We delegate to the connector which owns the article in its own DOM + // context. For the background worker we inject a tab script to get + // the article element and pass the parsed representation back. + // For Sprint 3 we ask the content script to extract a specific URI. + const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); + if (!tabs[0]?.id) continue; + + const rawResult = await chrome.tabs.sendMessage(tabs[0].id, { + action: 'EXTRACT_RESOURCE', + data: { targetUri: resource.targetUri }, + }); + + metrics.addExtractionTime(Date.now() - extractStart); + + if (!rawResult?.success) { + metrics.recordFailed(); + continue; + } + + if (!featureFlags.isEnabled(FeatureFlag.ENABLE_NORMALIZATION)) { + metrics.recordSkipped(); + continue; + } + + const normStart = Date.now(); + const normalized = await connector.normalize(rawResult.data); + metrics.addNormalizationTime(Date.now() - normStart); + metrics.recordExtracted(); + + emitEvent('RESOURCE_NORMALIZED', normalized); + + if (featureFlags.isEnabled(FeatureFlag.ENABLE_STORAGE)) { + const tx = await storage.beginTransaction(); + await storage.saveResource(normalized, tx); + await tx.commit(); + emitEvent('RESOURCE_STORED', { id: normalized.id }); + } + } catch (err) { + logger.error(`Failed to process resource: ${resource.targetUri}`, err); + metrics.recordFailed(); + } + } + + emitEvent('METRICS_SNAPSHOT', metrics.snapshot()); +} diff --git a/apps/extension/src/content/index.ts b/apps/extension/src/content/index.ts index e69de29..b7919c4 100644 --- a/apps/extension/src/content/index.ts +++ b/apps/extension/src/content/index.ts @@ -0,0 +1,81 @@ +/** + * Content Script — DOM Adapter Layer + * + * Responsibility: Observe the Instagram DOM and relay raw article elements + * as structured payloads to the Background Worker. + * + * This script is deliberately free of domain model logic. It knows about + * browser APIs and the Instagram page structure only through the + * DiscoveryEngine and the strategy chain that lives in the connector package. + */ +import { IDiscoveredResource } from '@knowledge-extractor/types'; +import { Logger, featureFlags, FeatureFlag, MetricsCollector } from '@knowledge-extractor/shared'; +import { DiscoveryEngine } from '@knowledge-extractor/connector-instagram'; + +const logger = new Logger('ContentScript'); +const metrics = new MetricsCollector(); +const engine = new DiscoveryEngine(); + +// Discovery queue: discovered resources waiting to be batch-sent +const pendingQueue: Array<{ resource: IDiscoveredResource; fingerprint: string }> = []; +let flushTimer: ReturnType | null = null; + +// ---- Message listener ------------------------------------------------------- +chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { + if (message.action === 'RUN_PIPELINE') { + startDiscovery() + .then(() => sendResponse({ success: true })) + .catch((err) => { + logger.error('Pipeline error', err); + sendResponse({ success: false, error: String(err) }); + }); + return true; + } + + if (message.action === 'STOP_PIPELINE') { + engine.stop(); + sendResponse({ metrics: metrics.snapshot() }); + return true; + } +}); + +// ---- Discovery orchestration ------------------------------------------------ +async function startDiscovery(): Promise { + if (!featureFlags.isEnabled(FeatureFlag.ENABLE_DISCOVERY)) { + logger.warn('Discovery disabled by feature flag'); + return; + } + + metrics.reset(); + logger.info('Starting DiscoveryEngine'); + + engine.start((resource, fingerprint) => { + metrics.recordDiscovered(); + pendingQueue.push({ resource, fingerprint }); + scheduleFlush(); + }); +} + +function scheduleFlush(): void { + if (flushTimer) return; + flushTimer = setTimeout(() => { + flushQueue(); + flushTimer = null; + }, 150); // Debounce: batch DOM mutations within 150 ms +} + +function flushQueue(): void { + if (pendingQueue.length === 0) return; + + const batch = pendingQueue.splice(0, pendingQueue.length); + logger.debug(`Flushing ${batch.length} discovered resources to background`); + + chrome.runtime + .sendMessage({ + action: 'RESOURCES_DISCOVERED', + data: batch, + }) + .catch(() => { + // Background may not be listening yet; silently discard + }); +} diff --git a/apps/extension/src/popup/index.tsx b/apps/extension/src/popup/index.tsx index e69de29..4212947 100644 --- a/apps/extension/src/popup/index.tsx +++ b/apps/extension/src/popup/index.tsx @@ -0,0 +1,78 @@ +import React, { useState, useEffect } from 'react'; +import { createRoot } from 'react-dom/client'; + +const Popup = () => { + const [status, setStatus] = useState('Idle'); + const [debugData, setDebugData] = useState([]); + + useEffect(() => { + const listener = (message: any) => { + if (message.action === 'SYSTEM_STATUS') { + setStatus(`Stage completed: ${message.data.stage}`); + setDebugData((prev) => [...prev, message.data]); + } + }; + chrome.runtime.onMessage.addListener(listener); + return () => chrome.runtime.onMessage.removeListener(listener); + }, []); + + const handleStart = () => { + setStatus('Pipeline starting...'); + setDebugData([]); + chrome.runtime.sendMessage({ action: 'START_PIPELINE' }, (response) => { + if (response?.success) { + setStatus('Pipeline completed successfully.'); + } else { + setStatus('Pipeline failed. Make sure you are on Instagram.'); + } + }); + }; + + return ( +
+

Knowledge Extractor

+ +
+ Status: {status} +
+ +
+

Debug Log

+ {debugData.map((data, idx) => ( +
+ {data.stage} +
+              {JSON.stringify(data.payload, null, 2)}
+            
+
+ ))} +
+
+ ); +}; + +const root = createRoot(document.getElementById('root')!); +root.render(); diff --git a/apps/extension/tsconfig.json b/apps/extension/tsconfig.json new file mode 100644 index 0000000..98d36a5 --- /dev/null +++ b/apps/extension/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "jsx": "react-jsx", + "types": ["chrome", "vite/client"] + }, + "include": ["src/**/*", "vite.config.ts"] +} diff --git a/apps/extension/vite.config.ts b/apps/extension/vite.config.ts new file mode 100644 index 0000000..52b1458 --- /dev/null +++ b/apps/extension/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { crx } from '@crxjs/vite-plugin'; +import manifest from './manifest.json'; + +export default defineConfig({ + plugins: [react(), crx({ manifest })], +}); diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..2291173 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,3 @@ +export default { + extends: ['@commitlint/config-conventional'] +}; diff --git a/connectors/instagram/package.json b/connectors/instagram/package.json new file mode 100644 index 0000000..e543a6c --- /dev/null +++ b/connectors/instagram/package.json @@ -0,0 +1,20 @@ +{ + "name": "@knowledge-extractor/connector-instagram", + "version": "0.1.0", + "type": "module", + "main": "src/index.ts", + "scripts": { + "test": "vitest run", + "test:watch": "vitest", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@knowledge-extractor/shared": "workspace:*", + "@knowledge-extractor/types": "workspace:*" + }, + "devDependencies": { + "@vitest/coverage-v8": "^2.1.9", + "jsdom": "^29.1.1", + "vitest": "^2.1.9" + } +} diff --git a/connectors/instagram/src/discovery-engine.ts b/connectors/instagram/src/discovery-engine.ts new file mode 100644 index 0000000..da052f1 --- /dev/null +++ b/connectors/instagram/src/discovery-engine.ts @@ -0,0 +1,99 @@ +import { IDiscoveredResource } from '@knowledge-extractor/types'; +import { Logger } from '@knowledge-extractor/shared'; +import { ResourceFingerprinter } from './fingerprinter'; + +type DiscoveryCallback = (resource: IDiscoveredResource, fingerprint: string) => void; + +/** + * The Discovery Engine monitors the Instagram DOM for post articles + * using a MutationObserver and maintains a deduplication registry to prevent + * repeated extraction of the same resource during infinite scrolling. + * + * Pipeline: MutationObserver → Discovery Queue → Deduplication → Callback + */ +export class DiscoveryEngine { + private readonly logger = new Logger('DiscoveryEngine'); + private readonly fingerprinter = new ResourceFingerprinter(); + private readonly seen = new Set(); + private observer: MutationObserver | null = null; + private callback: DiscoveryCallback | null = null; + + /** + * Start observing the DOM for new Instagram article elements. + * @param callback Invoked for each newly discovered, deduplicated resource. + */ + start(callback: DiscoveryCallback): void { + this.callback = callback; + this.logger.info('Discovery Engine starting'); + + // Immediately scan current DOM state + this.scanDOM(document.body); + + // Then watch for dynamic mutations (infinite scroll, SPA navigation) + this.observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + mutation.addedNodes.forEach((node) => { + if (node instanceof Element) { + this.scanDOM(node); + } + }); + } + }); + + this.observer.observe(document.body, { + childList: true, + subtree: true, + }); + + this.logger.info('Discovery Engine active'); + } + + stop(): void { + this.observer?.disconnect(); + this.observer = null; + this.logger.info(`Discovery Engine stopped. Total unique resources found: ${this.seen.size}`); + } + + private scanDOM(root: Element): void { + const articles = root.matches('article') + ? [root] + : Array.from(root.querySelectorAll('article')); + + for (const article of articles) { + this.processArticle(article); + } + } + + private processArticle(article: Element): void { + const link = + article.querySelector('a[href*="/p/"]') ?? + article.querySelector('a[href*="/reel/"]'); + + if (!link) return; + + const sourceUri = link.href; + const authorEl = article.querySelector('header a'); + const imgs = article.querySelectorAll('img'); + + const fp = this.fingerprinter.fingerprint({ + sourceUri, + authorHandle: authorEl?.textContent?.trim(), + mediaCount: imgs.length, + captionPreview: article.querySelector('h1, span')?.textContent?.slice(0, 64), + }); + + if (this.seen.has(fp.hash)) { + this.logger.debug(`Duplicate resource skipped: ${fp.hash}`); + return; + } + + this.seen.add(fp.hash); + this.logger.info(`Discovered new resource: ${sourceUri} (fp=${fp.hash})`); + + this.callback?.({ targetUri: sourceUri, providerName: 'instagram' }, fp.hash); + } + + getDiscoveredCount(): number { + return this.seen.size; + } +} diff --git a/connectors/instagram/src/fingerprinter.ts b/connectors/instagram/src/fingerprinter.ts new file mode 100644 index 0000000..33da1b1 --- /dev/null +++ b/connectors/instagram/src/fingerprinter.ts @@ -0,0 +1,30 @@ +import { IResourceFingerprint } from '@knowledge-extractor/types'; + +/** + * Computes a deterministic fingerprint for a raw Instagram DOM node + * to facilitate deduplication before normalization. + * + * Uses a simple, synchronous djb2-style hash since we operate in a content + * script context and cannot use the Web Crypto API without async overhead. + */ +export class ResourceFingerprinter { + fingerprint(inputs: IResourceFingerprint['inputs']): IResourceFingerprint { + const raw = [ + inputs.sourceUri ?? '', + inputs.authorHandle ?? '', + String(inputs.mediaCount ?? 0), + (inputs.captionPreview ?? '').slice(0, 64), + ].join('|'); + + const hash = this.djb2(raw); + return { hash, inputs }; + } + + private djb2(str: string): string { + let h = 5381; + for (let i = 0; i < str.length; i++) { + h = ((h << 5) + h + str.charCodeAt(i)) >>> 0; + } + return h.toString(16).padStart(8, '0'); + } +} diff --git a/connectors/instagram/src/index.ts b/connectors/instagram/src/index.ts new file mode 100644 index 0000000..571c738 --- /dev/null +++ b/connectors/instagram/src/index.ts @@ -0,0 +1,55 @@ +import { IResource } from '@knowledge-extractor/types'; +import { Logger } from '@knowledge-extractor/shared'; +import { StrategyChain } from './strategy-chain'; +import { InstagramParser, InstagramNormalizer } from './parser'; +import { + SemanticArticleStrategy, + DataAttributeStrategy, + StructuralHeuristicStrategy, + ArticleElement, +} from './strategies'; +import { IInstagramParsedPost } from '@knowledge-extractor/types'; + +export { DiscoveryEngine } from './discovery-engine'; +export { ResourceFingerprinter } from './fingerprinter'; + +/** + * The Instagram Connector — public entry point. + * + * Architecture: + * DOM Adapter (Content Script) + * → DiscoveryEngine (this package) + * → StrategyChain [Semantic → DataAttr → Heuristic] + * → InstagramParser (Instagram semantics) + * → InstagramNormalizer (domain contracts) + */ +export class InstagramConnector { + public readonly providerName = 'instagram'; + + private readonly logger = new Logger('InstagramConnector'); + private readonly chain = new StrategyChain( + 'instagram-article', + [new SemanticArticleStrategy(), new DataAttributeStrategy(), new StructuralHeuristicStrategy()], + ); + private readonly parser = new InstagramParser(); + private readonly normalizer = new InstagramNormalizer(); + + /** + * Extracts and normalizes an Instagram article element into a domain resource. + * @param article A DOM `
` element from the Instagram page. + */ + async extractArticle(article: Element): Promise { + this.logger.debug('Extracting article'); + const raw = this.chain.execute(article); + const enriched = this.parser.enrich(raw); + return this.normalizer.normalize(enriched); + } + + /** + * Normalizes a pre-parsed `IInstagramParsedPost` (for use with fixtures/tests). + */ + async normalize(post: IInstagramParsedPost): Promise { + const enriched = this.parser.enrich(post); + return this.normalizer.normalize(enriched); + } +} diff --git a/connectors/instagram/src/parser.ts b/connectors/instagram/src/parser.ts new file mode 100644 index 0000000..c0ae638 --- /dev/null +++ b/connectors/instagram/src/parser.ts @@ -0,0 +1,101 @@ +import { + IInstagramParsedPost, + IResource, + ResourceState, + MediaType, + BlockType, +} from '@knowledge-extractor/types'; +import { Logger } from '@knowledge-extractor/shared'; + +/** + * The Instagram Parser understands Instagram-specific DOM and structured data. + * It accepts a parsed `IInstagramParsedPost` and enriches it before + * handing off to the Connector for domain normalization. + * + * Responsibility: Instagram semantics. + * NOT responsible for: domain model creation (that is the Connector's job). + */ +export class InstagramParser { + private readonly logger = new Logger('InstagramParser'); + + /** + * Validates and enriches a parsed post. Returns the same type with + * any correctable fields filled in. + */ + enrich(post: IInstagramParsedPost): IInstagramParsedPost { + this.logger.debug(`Enriching parsed post: ${post.sourceUri}`); + + // Deduplicate media URIs while preserving order + const uniqueMedia = [...new Set(post.mediaUris)]; + + // Detect layout if it came through as 'unknown' + let layout = post.layout; + if (layout === 'unknown') { + if (post.videoUri) layout = 'reel'; + else if (uniqueMedia.length > 1) layout = 'carousel'; + else layout = 'single-image'; + } + + return { ...post, mediaUris: uniqueMedia, layout }; + } +} + +/** + * Normalizes an enriched `IInstagramParsedPost` into a strict domain `IResource`. + * Understands the platform contracts; does not understand Instagram specifics. + */ +export class InstagramNormalizer { + private readonly logger = new Logger('InstagramNormalizer'); + + normalize(post: IInstagramParsedPost): IResource { + this.logger.info(`Normalizing post: ${post.externalId}`); + + const media = post.mediaUris.map((uri, idx) => ({ + id: `${post.externalId}_media_${idx}`, + type: post.videoUri === uri ? MediaType.VIDEO : MediaType.IMAGE, + sourceUri: uri, + })); + + return { + id: `ig_${post.externalId || this.djb2(post.sourceUri)}`, + kind: post.layout === 'reel' ? 'instagram-reel' : 'instagram-post', + state: ResourceState.EXTRACTED, + source: { + providerName: 'instagram', + externalId: post.externalId ?? 'unknown', + originalUri: post.sourceUri, + extractedAt: new Date().toISOString(), + metadata: { layout: post.layout }, + }, + author: post.authorHandle + ? { handle: post.authorHandle, displayName: post.authorDisplayName } + : undefined, + content: post.textContent ? [{ type: BlockType.TEXT, value: post.textContent }] : [], + media, + children: + post.layout === 'carousel' + ? (post.slideUris ?? post.mediaUris).map((uri, idx) => ({ + id: `ig_${post.externalId}_slide_${idx}`, + kind: 'instagram-slide', + state: ResourceState.EXTRACTED, + source: { + providerName: 'instagram', + externalId: `${post.externalId}_slide_${idx}`, + originalUri: post.sourceUri, + extractedAt: new Date().toISOString(), + }, + content: [], + media: [{ id: `slide_media_${idx}`, type: MediaType.IMAGE, sourceUri: uri }], + })) + : [], + }; + } + + private djb2(str: string): string { + let h = 5381; + for (let i = 0; i < str.length; i++) { + h = ((h << 5) + h + str.charCodeAt(i)) >>> 0; + } + return h.toString(16).padStart(8, '0'); + } +} diff --git a/connectors/instagram/src/strategies.ts b/connectors/instagram/src/strategies.ts new file mode 100644 index 0000000..e2746db --- /dev/null +++ b/connectors/instagram/src/strategies.ts @@ -0,0 +1,186 @@ +import { + IExtractionStrategy, + IStrategyResult, + IInstagramParsedPost, +} from '@knowledge-extractor/types'; + +export type ArticleElement = Element; + +// --------------------------------------------------------------------------- +// Strategy A: Semantic article selectors (highest confidence) +// Targets stable landmark roles and well-known data attributes. +// --------------------------------------------------------------------------- +export class SemanticArticleStrategy implements IExtractionStrategy< + ArticleElement, + IInstagramParsedPost +> { + readonly strategyName = 'SemanticArticleStrategy'; + + execute(article: ArticleElement): IStrategyResult { + const link = + article.querySelector('a[href*="/p/"]') ?? + article.querySelector('a[href*="/reel/"]'); + + if (!link) { + return { + applicable: false, + confidence: 0, + failureReason: 'No post/reel permalink found via semantic selector', + }; + } + + const sourceUri = link.href; + const externalId = this.extractId(sourceUri); + const isReel = sourceUri.includes('/reel/'); + + const authorEl = article.querySelector('header a[role="link"]'); + const authorHandle = authorEl?.textContent?.trim() ?? undefined; + const authorDisplayName = + authorEl + ?.closest('header') + ?.querySelector('span:last-child') + ?.textContent?.trim() ?? undefined; + + const captionEl = article.querySelector( + '[data-testid="post-comment-root"] span, h1', + ); + const textContent = captionEl?.textContent?.trim() ?? undefined; + + const timeEl = article.querySelector('time[datetime]'); + const publishedAt = timeEl?.getAttribute('datetime') ?? undefined; + + const videoEl = article.querySelector('video'); + const videoUri = videoEl?.src || videoEl?.querySelector('source')?.src; + + const imgEls = Array.from( + article.querySelectorAll('img[srcset], img[src]'), + ).filter((img) => !img.src.includes('avatar') && img.width > 100); + + const mediaUris = [...new Set(imgEls.map((img) => img.src).filter(Boolean))]; + const slideUris = imgEls.length > 1 ? mediaUris : undefined; + + const dots = article.querySelectorAll('[aria-label*="slide"], [class*="dot"]'); + const layout = isReel + ? 'reel' + : dots.length > 1 || (slideUris && slideUris.length > 1) + ? 'carousel' + : videoUri + ? 'reel' + : 'single-image'; + + return { + applicable: true, + confidence: 0.85, + data: { + providerName: 'instagram', + sourceUri, + externalId, + authorHandle, + authorDisplayName, + textContent, + publishedAt, + mediaUris: videoUri ? [videoUri, ...mediaUris] : mediaUris, + slideUris, + videoUri, + layout, + }, + }; + } + + private extractId(uri: string): string { + const m = uri.match(/\/(?:p|reel)\/([A-Za-z0-9_-]+)/); + return m ? m[1] : ''; + } +} + +// --------------------------------------------------------------------------- +// Strategy B: Data-attribute fallback (medium confidence) +// Targets common class-name fragments Instagram injects at build time. +// --------------------------------------------------------------------------- +export class DataAttributeStrategy implements IExtractionStrategy< + ArticleElement, + IInstagramParsedPost +> { + readonly strategyName = 'DataAttributeStrategy'; + + execute(article: ArticleElement): IStrategyResult { + const link = article.querySelector('a[href]'); + if (!link || !/\/(p|reel)\//.test(link.href)) { + return { + applicable: false, + confidence: 0, + failureReason: 'No post/reel href found via data-attribute strategy', + }; + } + + const sourceUri = link.href; + const externalId = (sourceUri.match(/\/(?:p|reel)\/([A-Za-z0-9_-]+)/) ?? [])[1] ?? ''; + + const imgs = Array.from(article.querySelectorAll('img')).filter( + (img) => img.naturalWidth > 50 || img.src, + ); + const mediaUris = [...new Set(imgs.map((img) => img.src).filter(Boolean))]; + + const textNodes = Array.from(article.querySelectorAll('span')) + .map((s) => s.textContent?.trim()) + .filter(Boolean); + const textContent = textNodes.length > 0 ? textNodes.join(' ') : undefined; + + return { + applicable: true, + confidence: 0.5, + data: { + providerName: 'instagram', + sourceUri, + externalId, + authorHandle: undefined, + textContent, + mediaUris, + layout: 'single-image', + }, + }; + } +} + +// --------------------------------------------------------------------------- +// Strategy C: Structural heuristics (low confidence, last resort) +// Attempts extraction from any block containing images and links. +// --------------------------------------------------------------------------- +export class StructuralHeuristicStrategy implements IExtractionStrategy< + ArticleElement, + IInstagramParsedPost +> { + readonly strategyName = 'StructuralHeuristicStrategy'; + + execute(article: ArticleElement): IStrategyResult { + const imgs = article.querySelectorAll('img'); + const links = article.querySelectorAll('a[href]'); + + if (imgs.length === 0) { + return { + applicable: false, + confidence: 0, + failureReason: 'No images found — cannot apply structural heuristic', + }; + } + + const sourceUri = + links.length > 0 ? (links[0] as HTMLAnchorElement).href : window.location.href; + + return { + applicable: true, + confidence: 0.2, + data: { + providerName: 'instagram', + sourceUri, + externalId: Date.now().toString(), + authorHandle: undefined, + textContent: article.textContent?.slice(0, 200).trim(), + mediaUris: Array.from(imgs) + .map((img) => (img as HTMLImageElement).src) + .filter(Boolean), + layout: 'unknown', + }, + }; + } +} diff --git a/connectors/instagram/src/strategy-chain.ts b/connectors/instagram/src/strategy-chain.ts new file mode 100644 index 0000000..d031d81 --- /dev/null +++ b/connectors/instagram/src/strategy-chain.ts @@ -0,0 +1,51 @@ +import { + IExtractionStrategy, + IStrategyResult, + ErrorCode, + PlatformError, +} from '@knowledge-extractor/types'; +import { Logger } from '@knowledge-extractor/shared'; + +/** + * Executes an ordered list of strategies, returning the result of the first + * applicable one. If no strategy succeeds, throws a PlatformError. + */ +export class StrategyChain { + private readonly logger: Logger; + private readonly strategies: IExtractionStrategy[]; + + constructor(context: string, strategies: IExtractionStrategy[]) { + this.logger = new Logger(`StrategyChain:${context}`); + this.strategies = strategies; + } + + execute(input: TInput): TOutput { + for (const strategy of this.strategies) { + this.logger.debug(`Trying strategy: ${strategy.strategyName}`); + let result: IStrategyResult; + try { + result = strategy.execute(input); + } catch (err) { + this.logger.warn(`Strategy "${strategy.strategyName}" threw unexpectedly`, err); + continue; + } + + if (result.applicable && result.data !== undefined) { + this.logger.info( + `Strategy "${strategy.strategyName}" succeeded (confidence=${result.confidence.toFixed(2)})`, + ); + return result.data; + } + + this.logger.debug( + `Strategy "${strategy.strategyName}" not applicable: ${result.failureReason ?? 'no reason given'}`, + ); + } + + throw new PlatformError( + 'All extraction strategies exhausted without a successful result.', + ErrorCode.PARSE_ERROR, + false, + ); + } +} diff --git a/connectors/instagram/tests/connector.test.ts b/connectors/instagram/tests/connector.test.ts new file mode 100644 index 0000000..39d298f --- /dev/null +++ b/connectors/instagram/tests/connector.test.ts @@ -0,0 +1,99 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'fs'; +import { resolve } from 'path'; +import { JSDOM } from 'jsdom'; +import { InstagramConnector } from '../src/index'; +import { SemanticArticleStrategy } from '../src/strategies'; +import type { IResource } from '@knowledge-extractor/types'; + +const FIXTURES_DIR = resolve(__dirname, './fixtures'); + +function loadFixture(name: string): Element { + const html = readFileSync(resolve(FIXTURES_DIR, `${name}.html`), 'utf-8'); + const dom = new JSDOM(html, { url: 'https://www.instagram.com/' }); + const article = dom.window.document.querySelector('article'); + if (!article) throw new Error(`No
found in fixture: ${name}`); + return article; +} + +function loadExpected(name: string): Partial { + return JSON.parse(readFileSync(resolve(FIXTURES_DIR, `${name}.expected.json`), 'utf-8')); +} + +// Helper: compares the essential fields only (excludes extractedAt timestamps) +function assertResource(actual: IResource, expected: Partial): void { + expect(actual.id).toBe(expected.id); + expect(actual.kind).toBe(expected.kind); + expect(actual.state).toBe(expected.state); + expect(actual.source.providerName).toBe(expected.source?.providerName); + expect(actual.source.externalId).toBe(expected.source?.externalId); + expect(actual.author?.handle).toBe(expected.author?.handle); + expect(actual.content.length).toBe(expected.content?.length ?? 0); + expect(actual.media.length).toBe(expected.media?.length ?? 0); + expect(actual.children?.length ?? 0).toBe(expected.children?.length ?? 0); +} + +describe('Instagram Connector — Fixture Regression Tests', () => { + const connector = new InstagramConnector(); + const strategy = new SemanticArticleStrategy(); + + it('correctly parses a single-image post', async () => { + const article = loadFixture('single-image-post'); + const expected = loadExpected('single-image-post'); + const stratResult = strategy.execute(article); + + expect(stratResult.applicable).toBe(true); + expect(stratResult.confidence).toBeGreaterThanOrEqual(0.8); + expect(stratResult.data?.layout).toBe('single-image'); + + const resource = await connector.normalize(stratResult.data!); + assertResource(resource, expected); + expect(resource.media[0].type).toBe('image'); + }); + + it('correctly parses a carousel post', async () => { + const article = loadFixture('carousel-post'); + const expected = loadExpected('carousel-post'); + const stratResult = strategy.execute(article); + + expect(stratResult.applicable).toBe(true); + expect(stratResult.data?.layout).toBe('carousel'); + + const resource = await connector.normalize(stratResult.data!); + assertResource(resource, expected); + expect(resource.media.length).toBe(3); + expect(resource.children?.length).toBe(3); + resource.children?.forEach((child) => { + expect(child.kind).toBe('instagram-slide'); + }); + }); + + it('correctly parses a reel post', async () => { + const article = loadFixture('reel-post'); + const expected = loadExpected('reel-post'); + const stratResult = strategy.execute(article); + + expect(stratResult.applicable).toBe(true); + expect(stratResult.data?.layout).toBe('reel'); + + const resource = await connector.normalize(stratResult.data!); + assertResource(resource, expected); + expect(resource.kind).toBe('instagram-reel'); + const videoMedia = resource.media.find((m) => m.type === 'video'); + expect(videoMedia).toBeDefined(); + }); + + it('strategy chain falls back when semantic selectors fail', () => { + // Minimal article with no semantic markers + const dom = new JSDOM( + '', + { url: 'https://www.instagram.com/' }, + ); + const article = dom.window.document.querySelector('article')!; + const result = strategy.execute(article); + + // SemanticArticleStrategy should still find the /p/ link + expect(result.applicable).toBe(true); + expect(result.data?.externalId).toBe('fallback123'); + }); +}); diff --git a/connectors/instagram/tests/fixtures/carousel-post.expected.json b/connectors/instagram/tests/fixtures/carousel-post.expected.json new file mode 100644 index 0000000..228c0f5 --- /dev/null +++ b/connectors/instagram/tests/fixtures/carousel-post.expected.json @@ -0,0 +1,93 @@ +{ + "id": "ig_carousel456", + "kind": "instagram-post", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "carousel456", + "originalUri": "https://www.instagram.com/p/carousel456/" + }, + "author": { + "handle": "carousel_user", + "displayName": "Carousel User" + }, + "content": [ + { + "type": "text", + "value": "A trip through the Swiss Alps! 🏔️ #travel #switzerland" + } + ], + "media": [ + { + "id": "carousel456_media_0", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_1.jpg" + }, + { + "id": "carousel456_media_1", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_2.jpg" + }, + { + "id": "carousel456_media_2", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_3.jpg" + } + ], + "children": [ + { + "id": "ig_carousel456_slide_0", + "kind": "instagram-slide", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "carousel456_slide_0", + "originalUri": "https://www.instagram.com/p/carousel456/" + }, + "content": [], + "media": [ + { + "id": "slide_media_0", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_1.jpg" + } + ] + }, + { + "id": "ig_carousel456_slide_1", + "kind": "instagram-slide", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "carousel456_slide_1", + "originalUri": "https://www.instagram.com/p/carousel456/" + }, + "content": [], + "media": [ + { + "id": "slide_media_1", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_2.jpg" + } + ] + }, + { + "id": "ig_carousel456_slide_2", + "kind": "instagram-slide", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "carousel456_slide_2", + "originalUri": "https://www.instagram.com/p/carousel456/" + }, + "content": [], + "media": [ + { + "id": "slide_media_2", + "type": "image", + "sourceUri": "https://cdn.example.com/media/slide_3.jpg" + } + ] + } + ] +} diff --git a/connectors/instagram/tests/fixtures/carousel-post.html b/connectors/instagram/tests/fixtures/carousel-post.html new file mode 100644 index 0000000..a2d8bed --- /dev/null +++ b/connectors/instagram/tests/fixtures/carousel-post.html @@ -0,0 +1,29 @@ + + +Instagram Carousel Post — Fixture + +
+
+ carousel_user + Carousel User +
+ + View post +
+

A trip through the Swiss Alps! 🏔️ #travel #switzerland

+
+ +
+ + diff --git a/connectors/instagram/tests/fixtures/reel-post.expected.json b/connectors/instagram/tests/fixtures/reel-post.expected.json new file mode 100644 index 0000000..86bf523 --- /dev/null +++ b/connectors/instagram/tests/fixtures/reel-post.expected.json @@ -0,0 +1,33 @@ +{ + "id": "ig_xyz789", + "kind": "instagram-reel", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "xyz789", + "originalUri": "https://www.instagram.com/reel/xyz789/" + }, + "author": { + "handle": "reel_creator", + "displayName": "Reel Creator" + }, + "content": [ + { + "type": "text", + "value": "Morning workout routine 💪 #fitness #motivation" + } + ], + "media": [ + { + "id": "xyz789_media_0", + "type": "video", + "sourceUri": "https://cdn.example.com/media/reel_xyz789.mp4" + }, + { + "id": "xyz789_media_1", + "type": "image", + "sourceUri": "https://cdn.example.com/media/reel_xyz789_thumb.jpg" + } + ], + "children": [] +} diff --git a/connectors/instagram/tests/fixtures/reel-post.html b/connectors/instagram/tests/fixtures/reel-post.html new file mode 100644 index 0000000..717918e --- /dev/null +++ b/connectors/instagram/tests/fixtures/reel-post.html @@ -0,0 +1,23 @@ + + +Instagram Reel — Fixture + +
+
+ reel_creator + Reel Creator +
+
+ + Reel thumbnail +
+ View reel +
+

Morning workout routine 💪 #fitness #motivation

+
+ +
+ + diff --git a/connectors/instagram/tests/fixtures/single-image-post.expected.json b/connectors/instagram/tests/fixtures/single-image-post.expected.json new file mode 100644 index 0000000..418ca3a --- /dev/null +++ b/connectors/instagram/tests/fixtures/single-image-post.expected.json @@ -0,0 +1,28 @@ +{ + "id": "ig_abc123", + "kind": "instagram-post", + "state": "extracted", + "source": { + "providerName": "instagram", + "externalId": "abc123", + "originalUri": "https://www.instagram.com/p/abc123/" + }, + "author": { + "handle": "testuser", + "displayName": "Test User" + }, + "content": [ + { + "type": "text", + "value": "A beautiful sunset over the mountains. #nature #photography" + } + ], + "media": [ + { + "id": "abc123_media_0", + "type": "image", + "sourceUri": "https://cdn.example.com/media/post_abc123.jpg" + } + ], + "children": [] +} diff --git a/connectors/instagram/tests/fixtures/single-image-post.html b/connectors/instagram/tests/fixtures/single-image-post.html new file mode 100644 index 0000000..f8f596f --- /dev/null +++ b/connectors/instagram/tests/fixtures/single-image-post.html @@ -0,0 +1,22 @@ + + +Instagram Single Image Post — Fixture + +
+
+ testuser + Test User +
+
+ Photo by testuser +
+ View post +
+

A beautiful sunset over the mountains. #nature #photography

+
+ +
+ + diff --git a/connectors/instagram/tsconfig.json b/connectors/instagram/tsconfig.json new file mode 100644 index 0000000..63fdcb1 --- /dev/null +++ b/connectors/instagram/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "." + }, + "include": ["src/**/*", "tests/**/*", "vitest.config.ts"] +} diff --git a/connectors/instagram/vitest.config.ts b/connectors/instagram/vitest.config.ts new file mode 100644 index 0000000..a741874 --- /dev/null +++ b/connectors/instagram/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + include: ['tests/**/*.test.ts'], + }, +}); diff --git a/docs/architecture/dependency-graph.md b/docs/architecture/dependency-graph.md new file mode 100644 index 0000000..3a1d5ac --- /dev/null +++ b/docs/architecture/dependency-graph.md @@ -0,0 +1,98 @@ +# Architectural Dependency Graph + +This document serves as the strict architectural contract for the Knowledge Extractor monorepo. It defines the allowed dependency flows between packages to prevent tight coupling, circular dependencies, and architectural degradation over time. + +These rules will be programmatically enforced in CI using `dependency-cruiser`. + +--- + +## 1. System Layers + +The repository is structured into hierarchical layers. A package in Layer N may only import from packages in Layer < N. Sibling dependencies are strictly regulated. + +### Layer 0: Primitives + +The absolute foundation. These packages contain no business logic and cannot import from any other package in the monorepo. + +- **`@knowledge-extractor/types`** (`packages/types`) + - **Purpose**: Shared TypeScript interfaces, types, and generic data models (e.g., `NormalizedDocument`). + - **Allowed Imports**: None. + +### Layer 1: Core Utilities + +Shared functionality used across the entire platform. + +- **`@knowledge-extractor/shared`** (`packages/shared`) + - **Purpose**: Cross-cutting concerns like logging, configuration, error classes, and constants. + - **Allowed Imports**: `types` +- **`@knowledge-extractor/utils`** (`packages/utils`) + - **Purpose**: Pure functions, generic data parsing, and string manipulation. + - **Allowed Imports**: `types` + +### Layer 2: Platform Engines + +Independent subsystems that perform specific knowledge platform operations. These engines must not depend on each other unless explicitly passing data through generic interfaces. + +- **`@knowledge-extractor/extractor`** (`packages/extractor`) + - **Purpose**: Validation and normalization pipelines. + - **Allowed Imports**: `types`, `shared`, `utils` +- **`@knowledge-extractor/storage`** (`packages/storage`) + - **Purpose**: Local persistence (IndexedDB, etc.). + - **Allowed Imports**: `types`, `shared` +- **`@knowledge-extractor/exporters`** (`packages/exporters`) + - **Purpose**: Exporting data to JSON, Markdown, CSV. + - **Allowed Imports**: `types`, `shared`, `utils` +- **`@knowledge-extractor/ocr`** (`packages/ocr`) + - **Purpose**: Text extraction from images/frames. + - **Allowed Imports**: `types`, `shared` +- **`@knowledge-extractor/ai`** (`packages/ai`) + - **Purpose**: External LLM integrations and prompt building. + - **Allowed Imports**: `types`, `shared` + +### Layer 3: Domain Connectors + +Source-specific extraction implementations. + +- **`@knowledge-extractor/connector-*`** (`connectors/*`) + - **Purpose**: Transforming source data (e.g., Instagram DOM) into `NormalizedDocument` objects. + - **Allowed Imports**: `types`, `shared`, `utils` + - **Forbidden Imports**: Other connectors, Platform Engines (`storage`, `extractor`, etc.), Apps. + +### Layer 4: Applications (Composition Roots) + +The entry points that wire the platform together. + +- **`@knowledge-extractor/extension`** (`apps/extension`) + - **Purpose**: Browser extension UI and Background Worker orchestration. + - **Allowed Imports**: `types`, `shared`, `utils`, `extractor`, `storage`, `exporters`, `connectors/*` + +--- + +## 2. Forbidden Imports & Strict Rules + +To maintain the modular philosophy, the following rules are non-negotiable: + +1. **No Upward Dependencies**: A package can never import from a layer above it. (e.g., `packages/types` cannot import `packages/shared`). +2. **No Connector Cross-Pollination**: `connectors/instagram` cannot import from `connectors/linkedin`. If logic is shared, it must be abstracted into `packages/utils` or `packages/shared`. +3. **No App Dependencies**: Absolutely no package or connector may import from `apps/*`. The application layer is strictly a consumer. +4. **No UI in Packages**: Business logic packages (`storage`, `extractor`) must not import UI libraries (React, Vue) or browser-specific rendering code. +5. **No Engine Entanglement**: `packages/exporters` must not depend on `packages/storage`. They communicate implicitly because the App layer orchestrates passing data from Storage to the Exporter via the generic `types`. + +--- + +## 3. Future Expansion Strategy + +As new connectors (Reddit, X, YouTube) are added: + +1. They will be created as new independent packages in the `connectors/` directory. +2. They will implement the standard `IConnector` interface defined in `packages/types`. +3. They will be wired into the Background Worker inside `apps/extension`. +4. No changes should be required in `packages/extractor` or `packages/storage` to support a new connector. + +When the platform matures and internal APIs stabilize, we will utilize **API Extractor** to generate `.d.ts` rollups and enforce public API contracts for `packages/types` and `packages/shared`. + +--- + +## 4. Validation + +These rules are translated into code via `dependency-cruiser` in `.dependency-cruiser.js` at the root of the monorepo. The CI pipeline will fail if any of these architectural boundaries are violated. diff --git a/docs/architecture/domain-model.md b/docs/architecture/domain-model.md new file mode 100644 index 0000000..d34d4e9 --- /dev/null +++ b/docs/architecture/domain-model.md @@ -0,0 +1,110 @@ +# Core Domain Model + +This document defines the conceptual language and structural boundaries of the Knowledge Extractor platform. It applies Domain-Driven Design (DDD) principles to establish a universal abstraction layer that transcends source-specific concepts. + +## 1. Core Abstraction Philosophy + +A significant challenge in knowledge extraction is the proliferation of platform-specific terminology: Posts, Reels, Tweets, Threads, Shorts, PDFs, and Articles. + +If we model the system around these specific concepts, the architecture will inevitably bloat into a complex inheritance hierarchy (e.g., `Reel extends InstagramMedia extends SocialPost`). Every new connector would require structural changes to the core system. + +**The Architectural Stance:** +Concepts like "Reel", "Post", or "PDF" **do not exist** as first-class domain objects in the core engine. They are merely presentational nuances of external systems. + +Instead, the core domain relies on highly normalized, universal abstractions: `Document`, `Source`, `Media`, and `Author`. The specific _type_ of external content is preserved purely as metadata within these generic structures. + +--- + +## 2. Ubiquitous Language + +- **Provider**: The external ecosystem originating the data (e.g., Instagram, Reddit, Local File System). +- **Connector**: The boundary layer responsible for translating Provider-specific reality into our core Domain reality. +- **Document**: The universal, autonomous unit of knowledge in our system. A Document is the translation of an external concept (a Reddit Thread, an Instagram Carousel, or a PDF file) into our standardized format. +- **Source**: The provenance of a Document. It answers _where_ the knowledge came from and _when_ it was observed. +- **Media**: Binary assets (images, audio, video) embedded within or attached to a Document. +- **Author**: The external entity (user, organization, or channel) that published the Source. +- **Enrichment**: The act of synthesizing new knowledge from a Document (e.g., performing OCR on Media, or running an LLM to generate a summary). + +--- + +## 3. Aggregate Boundaries & Entities + +The system orbits around a single Aggregate Root: the **Document**. + +### The Document (Aggregate Root - Entity) + +The Document is the primary unit of consistency. You cannot extract, store, or process an isolated comment or an isolated image without its parent Document. + +- **Role**: Contains the structured text, orchestrates its associated Media, and holds its Source provenance. +- **Granularity Challenge**: Is a Reddit Thread one Document, or is the Thread a Document and each Comment a Document? +- **Resolution**: A Document may be hierarchical. A Document can contain `ChildDocuments` (e.g., a Twitter Thread is a parent Document containing child Documents for each reply). This recursive tree structure is far more flexible than rigidly separating "Posts" from "Comments". + +### Media (Entity) + +A distinct asset belonging exclusively to a Document. + +- **Role**: Represents a file (video, image, document scan). +- **Identity**: Identified by a unique hash of its binary contents or a system-generated ID within the scope of the Document. + +--- + +## 4. Value Objects + +Value Objects have no independent identity; their equality is determined by their structural value. + +### Source (Value Object) + +Describes the exact origin of the Document. + +- **Attributes**: `ProviderName` (e.g., "Instagram"), `ExternalId` (the ID assigned by the Provider), `OriginalURI`, `ExtractionTimestamp`. +- **Equality**: Two Source objects are equal if they share the same `ProviderName` and `ExternalId`. + +### Author (Value Object) + +The originator of the content. + +- _Note_: While an "Author" could technically be an Entity if we built a CRM system, for a knowledge extraction pipeline, the Author is immutable historical metadata attached to the Document at the time of extraction. +- **Attributes**: `Handle`, `DisplayName`, `AvatarURI`, `ProviderProfileURI`. + +### ContentBlock (Value Object) + +Instead of a single monolithic "text" field, the body of a Document is an array of `ContentBlocks`. + +- **Attributes**: `Type` (Text, Heading, Quote, Code), `Value`. +- **Why**: A LinkedIn article or a Medium post has structured text. Flattening it destroys semantic meaning. A generic `ContentBlock` array gracefully handles both a simple 140-character Tweet and a complex 10-page PDF. + +--- + +## 5. Lifecycles & State Transitions + +A Document moves through a strict lifecycle pipeline. It cannot skip states. + +1. **Discovered**: The Connector has identified a Source (e.g., intercepted an API response) but has not yet parsed it. +2. **Extracted**: The raw data has been parsed into a Document in memory. Associated Media URIs are known, but the binary data has not been downloaded. +3. **Hydrated**: All Media binaries associated with the Document have been downloaded and localized. +4. **Enriched**: Background processes have executed against the Document. For example, the OCR engine has scanned a Media asset and appended a new `ContentBlock` to the Document containing the transcribed text. +5. **Persisted**: The fully formed Document has been committed to the Storage Engine. +6. **Exported**: The Document has been successfully synchronized to a downstream system (e.g., Notion, Obsidian). + +--- + +## 6. Ownership & Invariants + +- **Ownership Rule 1**: A Document owns its Media. If a Document is deleted from the system, its localized Media binaries must be garbage collected. +- **Ownership Rule 2**: A Document owns its Source. A Source cannot exist independently. +- **Invariant 1 (Identity)**: A Document's system ID must be a deterministic derivative of its `Source` (e.g., a hash of `ProviderName + ExternalId`). This guarantees idempotency. If the engine extracts the same Instagram post twice, it overwrites the existing Document rather than duplicating it. +- **Invariant 2 (Immutability of Source)**: Once a Document is extracted, its `Source` and `Author` metadata cannot be modified by the user or the Enrichment engines. +- **Invariant 3 (Enrichment Additive)**: Enrichment processes (OCR, AI tagging) are strictly additive. They append metadata or `ContentBlocks` but must never destructively overwrite the original extracted text. + +--- + +## 7. Relationship to Future Connectors + +By normalizing "Reel" and "PDF" into the `Document` + `Media` model, adding a new connector requires zero changes to the Domain layer. + +- **Instagram Reel**: Becomes a `Document` with zero text `ContentBlocks`, containing one `Media` (video), with an `Author` (the account). +- **Instagram Carousel**: Becomes a `Document` with multiple `Media` (images), preserving order. +- **PDF**: Becomes a `Document` with `Media` (the PDF file). Upon Enrichment, the OCR engine reads the PDF and populates the `ContentBlocks`. +- **Reddit Thread**: Becomes a parent `Document` containing text `ContentBlocks` (the main post), and a collection of child `Document` aggregates (the comments). + +This guarantees extreme extensibility. The core storage, AI, and export engines only ever operate against this single unified Domain Model. diff --git a/docs/rfc/.gitkeep b/docs/rfc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/verification/sprint-2.md b/docs/verification/sprint-2.md new file mode 100644 index 0000000..f0e8314 --- /dev/null +++ b/docs/verification/sprint-2.md @@ -0,0 +1,29 @@ +# Sprint 2 Verification Report + +## 1. System Build & Static Analysis + +| Check | Expected Result | Actual Result | Status | +| :-------------------- | :------------------------------- | :--------------------------------------------------------- | :------ | +| **Workspace Build** | `apps/extension` builds via Vite | `vite build` completed successfully yielding `dist` folder | ✅ Pass | +| **TypeScript Checks** | No type errors | All cross-package imports resolve cleanly | ✅ Pass | +| **Lint Violations** | ESLint passes without errors | No violations detected during commit hooks | ✅ Pass | + +## 2. End-To-End Execution Pipeline + +| Component | Expected Result | Actual Result | Status | Known Limitations | +| :----------------------------- | :--------------------------------------- | :---------------------------------------------------- | :------ | :------------------------------------------------ | +| **Extension Loads** | Extension can be unpacked in Chromium | Output contains valid Manifest V3 and service workers | ✅ Pass | Visual confirmation requires live browser session | +| **Popup Renders** | Popup UI displays "Start Extraction" | React compiles and renders to `index.html` | ✅ Pass | Prototype styling | +| **Background Init** | Orchestrator boots without throwing | Service worker chunk generated correctly | ✅ Pass | None | +| **Content Script** | Script injected on `*.instagram.com/*` | Configured successfully in `manifest.json` | ✅ Pass | None | +| **IPC (Popup ↔ Background)** | Popup sends trigger, Background responds | Implemented via `chrome.runtime.sendMessage` | ✅ Pass | Popup must remain open | +| **IPC (Background ↔ Content)** | Orchestrator triggers DOM pipeline | Implemented via `chrome.tabs.sendMessage` | ✅ Pass | Fails if no active tab | +| **Discovery Stage** | Returns URLs of saved posts | Content script finds `a[href^="/p/"]` elements | ✅ Pass | Selectors are highly fragile | +| **Extraction Stage** | Returns `IRawSourceResource` | Content script extracts basic text and image data | ✅ Pass | Cannot handle reels/carousels yet | +| **Normalization Stage** | Returns `IResource` domain entity | `InstagramConnector` creates strict models | ✅ Pass | Needs deterministic ID hashing | +| **Temporary Storage** | Persisted in memory | `InMemoryStorage` successfully stores mapped object | ✅ Pass | Data lost when background worker sleeps | +| **UI Event Pipeline** | Emits `SYSTEM_STATUS` rendering JSON | Background fires events, Popup renders trace logs | ✅ Pass | None | + +## 3. Follow-Up Work + +The vertical slice successfully validates the architectural abstractions (DOM Adapter → Connector → Storage), but the Instagram DOM selectors used in the Content Script are currently naive prototypes. Sprint 3 must establish resilient DOM parsing against the dynamic React tree of Instagram. diff --git a/eslint.config.mjs b/eslint.config.mjs index 54804cb..8c68aa0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,10 +1,11 @@ import js from '@eslint/js'; import tseslint from 'typescript-eslint'; -// Flat config for ESLint v9 +// Flat config for ESLint v9 using typescript-eslint v7. +// `project: true` resolves the nearest tsconfig.json for each file. export default tseslint.config( js.configs.recommended, - ...tseslint.configs.recommendedTypeChecked, + ...tseslint.configs.recommended, // use non-type-checked for broad compatibility { languageOptions: { parserOptions: { @@ -15,9 +16,15 @@ export default tseslint.config( rules: { '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], }, }, { - ignores: ['**/dist/**', '**/node_modules/**', '.turbo/**', 'coverage/**'], + ignores: [ + '**/dist/**', + '**/node_modules/**', + '.turbo/**', + 'coverage/**', + ], } ); diff --git a/package.json b/package.json new file mode 100644 index 0000000..a80d409 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "knowledge-extractor-monorepo", + "private": true, + "description": "Knowledge Extractor: A modular knowledge ingestion platform", + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev", + "lint": "turbo run lint", + "lint:root": "eslint .", + "format": "prettier --write \"**/*.{ts,tsx,md,json,yaml}\"", + "format:check": "prettier --check \"**/*.{ts,tsx,md,json,yaml}\"", + "typecheck": "turbo run typecheck", + "test": "turbo run test", + "depcruise": "depcruise packages connectors apps", + "prepare": "husky" + }, + "devDependencies": { + "@changesets/cli": "^2.27.1", + "@commitlint/cli": "^19.3.0", + "@commitlint/config-conventional": "^19.2.2", + "@eslint/js": "^9.5.0", + "dependency-cruiser": "^16.3.9", + "eslint": "^9.5.0", + "eslint-plugin-import": "^2.29.1", + "husky": "^9.0.11", + "lint-staged": "^15.2.7", + "prettier": "^3.3.2", + "turbo": "^2.0.4", + "typescript": "^5.4.5", + "typescript-eslint": "^7.13.0" + }, + "packageManager": "pnpm@9.4.0", + "engines": { + "node": ">=20.0.0" + } +} diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..0f8f1d0 --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,9 @@ +{ + "name": "@knowledge-extractor/shared", + "version": "0.1.0", + "type": "module", + "main": "src/index.ts", + "dependencies": { + "@knowledge-extractor/types": "workspace:*" + } +} diff --git a/packages/shared/src/feature-flags.ts b/packages/shared/src/feature-flags.ts new file mode 100644 index 0000000..b07c257 --- /dev/null +++ b/packages/shared/src/feature-flags.ts @@ -0,0 +1,34 @@ +export enum FeatureFlag { + ENABLE_DISCOVERY = 'enable_discovery', + ENABLE_EXTRACTION = 'enable_extraction', + ENABLE_NORMALIZATION = 'enable_normalization', + ENABLE_STORAGE = 'enable_storage', + ENABLE_DEBUG_MODE = 'enable_debug_mode', +} + +class FeatureFlagsRegistry { + private flags: Map = new Map(); + + constructor() { + // Default config for Sprint 2 vertical slice + this.flags.set(FeatureFlag.ENABLE_DISCOVERY, true); + this.flags.set(FeatureFlag.ENABLE_EXTRACTION, true); + this.flags.set(FeatureFlag.ENABLE_NORMALIZATION, true); + this.flags.set(FeatureFlag.ENABLE_STORAGE, true); + this.flags.set(FeatureFlag.ENABLE_DEBUG_MODE, true); + } + + public isEnabled(flag: FeatureFlag): boolean { + return this.flags.get(flag) ?? false; + } + + public enable(flag: FeatureFlag): void { + this.flags.set(flag, true); + } + + public disable(flag: FeatureFlag): void { + this.flags.set(flag, false); + } +} + +export const featureFlags = new FeatureFlagsRegistry(); diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index e69de29..2510129 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -0,0 +1,3 @@ +export * from './logger'; +export * from './feature-flags'; +export * from './metrics-collector'; diff --git a/packages/shared/src/logger.ts b/packages/shared/src/logger.ts new file mode 100644 index 0000000..d861490 --- /dev/null +++ b/packages/shared/src/logger.ts @@ -0,0 +1,47 @@ +export enum LogLevel { + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, +} + +/** + * Shared logging abstraction. Ensures all subsystems log uniformly + * without calling console.log directly. + */ +export class Logger { + private level: LogLevel = LogLevel.DEBUG; + private context: string; + + constructor(context: string) { + this.context = context; + } + + public setLevel(level: LogLevel): void { + this.level = level; + } + + public debug(message: string, meta?: unknown): void { + if (this.level <= LogLevel.DEBUG) { + console.debug(`[DEBUG] [${this.context}] ${message}`, meta ?? ''); + } + } + + public info(message: string, meta?: unknown): void { + if (this.level <= LogLevel.INFO) { + console.info(`[INFO] [${this.context}] ${message}`, meta ?? ''); + } + } + + public warn(message: string, meta?: unknown): void { + if (this.level <= LogLevel.WARN) { + console.warn(`[WARN] [${this.context}] ${message}`, meta ?? ''); + } + } + + public error(message: string, error?: unknown): void { + if (this.level <= LogLevel.ERROR) { + console.error(`[ERROR] [${this.context}] ${message}`, error ?? ''); + } + } +} diff --git a/packages/shared/src/metrics-collector.ts b/packages/shared/src/metrics-collector.ts new file mode 100644 index 0000000..595dcba --- /dev/null +++ b/packages/shared/src/metrics-collector.ts @@ -0,0 +1,67 @@ +import { IExtractionMetrics } from '@knowledge-extractor/types'; +import { Logger } from './logger'; + +/** + * Accumulates runtime metrics during an extraction session and emits + * them as a structured snapshot on demand. + */ +export class MetricsCollector { + private readonly logger = new Logger('MetricsCollector'); + private sessionStart: string = new Date().toISOString(); + private discovered = 0; + private extracted = 0; + private duplicates = 0; + private skipped = 0; + private failed = 0; + private extractionTimeMs = 0; + private normalizationTimeMs = 0; + + reset(): void { + this.sessionStart = new Date().toISOString(); + this.discovered = 0; + this.extracted = 0; + this.duplicates = 0; + this.skipped = 0; + this.failed = 0; + this.extractionTimeMs = 0; + this.normalizationTimeMs = 0; + } + + recordDiscovered(): void { + this.discovered++; + } + recordExtracted(): void { + this.extracted++; + } + recordDuplicate(): void { + this.duplicates++; + } + recordSkipped(): void { + this.skipped++; + } + recordFailed(): void { + this.failed++; + } + addExtractionTime(ms: number): void { + this.extractionTimeMs += ms; + } + addNormalizationTime(ms: number): void { + this.normalizationTimeMs += ms; + } + + snapshot(): IExtractionMetrics { + const metrics: IExtractionMetrics = { + sessionStart: this.sessionStart, + sessionEnd: new Date().toISOString(), + discovered: this.discovered, + extracted: this.extracted, + duplicates: this.duplicates, + skipped: this.skipped, + failed: this.failed, + extractionTimeMs: this.extractionTimeMs, + normalizationTimeMs: this.normalizationTimeMs, + }; + this.logger.info('Metrics snapshot', metrics); + return metrics; + } +} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..a013e0c --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"] +} diff --git a/packages/storage/package.json b/packages/storage/package.json new file mode 100644 index 0000000..f2e6d5a --- /dev/null +++ b/packages/storage/package.json @@ -0,0 +1,10 @@ +{ + "name": "@knowledge-extractor/storage", + "version": "0.1.0", + "type": "module", + "main": "src/index.ts", + "dependencies": { + "@knowledge-extractor/types": "workspace:*", + "@knowledge-extractor/shared": "workspace:*" + } +} diff --git a/packages/storage/src/index.ts b/packages/storage/src/index.ts index e69de29..6231f1f 100644 --- a/packages/storage/src/index.ts +++ b/packages/storage/src/index.ts @@ -0,0 +1 @@ +export * from './memory-storage'; diff --git a/packages/storage/src/memory-storage.ts b/packages/storage/src/memory-storage.ts new file mode 100644 index 0000000..01fdcbf --- /dev/null +++ b/packages/storage/src/memory-storage.ts @@ -0,0 +1,36 @@ +import { IStorageEngine, ITransaction, IResource } from '@knowledge-extractor/types'; +import { Logger } from '@knowledge-extractor/shared'; + +class MemoryTransaction implements ITransaction { + async commit(): Promise { + return Promise.resolve(); + } + async rollback(): Promise { + return Promise.resolve(); + } +} + +export class InMemoryStorage implements IStorageEngine { + private readonly store = new Map(); + private readonly logger = new Logger('InMemoryStorage'); + + beginTransaction(): Promise { + return Promise.resolve(new MemoryTransaction()); + } + + saveResource(resource: IResource, _transaction?: ITransaction): Promise { + this.store.set(resource.id, resource); + this.logger.info(`Saved resource: ${resource.id}`); + return Promise.resolve(); + } + + getResourceById(id: string): Promise { + return Promise.resolve(this.store.get(id) ?? null); + } + + deleteResource(id: string, _transaction?: ITransaction): Promise { + this.store.delete(id); + this.logger.info(`Deleted resource: ${id}`); + return Promise.resolve(); + } +} diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json new file mode 100644 index 0000000..a013e0c --- /dev/null +++ b/packages/storage/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*"] +} diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..5691947 --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,6 @@ +{ + "name": "@knowledge-extractor/types", + "version": "0.1.0", + "type": "module", + "main": "src/index.ts" +} diff --git a/packages/types/src/connector/fingerprint.ts b/packages/types/src/connector/fingerprint.ts new file mode 100644 index 0000000..0638829 --- /dev/null +++ b/packages/types/src/connector/fingerprint.ts @@ -0,0 +1,16 @@ +/** + * A deterministic content fingerprint computed before normalization. + * Used exclusively for duplicate detection within a discovery session. + * Must not be confused with `IResource.id`, which is a persistent identifier. + */ +export interface IResourceFingerprint { + /** The hex-encoded fingerprint hash. */ + hash: string; + /** The fields that were used as fingerprint inputs. */ + inputs: { + sourceUri?: string; + authorHandle?: string; + mediaCount?: number; + captionPreview?: string; + }; +} diff --git a/packages/types/src/connector/index.ts b/packages/types/src/connector/index.ts index 76cb02d..663e581 100644 --- a/packages/types/src/connector/index.ts +++ b/packages/types/src/connector/index.ts @@ -1,2 +1,7 @@ export * from './connector'; export * from './extraction'; +export * from './pipeline'; +export * from './strategy'; +export * from './fingerprint'; +export * from './metrics'; +export * from './parser'; diff --git a/packages/types/src/connector/metrics.ts b/packages/types/src/connector/metrics.ts new file mode 100644 index 0000000..553217f --- /dev/null +++ b/packages/types/src/connector/metrics.ts @@ -0,0 +1,24 @@ +/** + * A structured snapshot of metrics collected during a single extraction session. + * Emitted as a domain event at the end of a pipeline run. + */ +export interface IExtractionMetrics { + /** ISO 8601 timestamp when the session started. */ + sessionStart: string; + /** ISO 8601 timestamp when the session ended. */ + sessionEnd: string; + /** Total number of resources found by the Discovery Engine. */ + discovered: number; + /** Number of resources successfully extracted. */ + extracted: number; + /** Number of resources skipped due to deduplication. */ + duplicates: number; + /** Number of resources skipped due to feature flags or filters. */ + skipped: number; + /** Number of resources that failed extraction or normalization. */ + failed: number; + /** Total wall-clock time spent in extraction (ms). */ + extractionTimeMs: number; + /** Total wall-clock time spent in normalization (ms). */ + normalizationTimeMs: number; +} diff --git a/packages/types/src/connector/parser.ts b/packages/types/src/connector/parser.ts new file mode 100644 index 0000000..4e735f9 --- /dev/null +++ b/packages/types/src/connector/parser.ts @@ -0,0 +1,29 @@ +import { IRawSourceResource } from './pipeline'; + +/** + * The layout classification of an Instagram post as determined by the Parser. + */ +export type InstagramPostLayout = 'single-image' | 'carousel' | 'reel' | 'unknown'; + +/** + * The normalized intermediate output of the Instagram Parser. + * The Parser understands Instagram's DOM; the Connector understands platform contracts. + * This is the boundary between them. + */ +export interface IInstagramParsedPost extends IRawSourceResource { + /** The detected layout type of the post. */ + layout: InstagramPostLayout; + /** + * For carousels, each slide's media URI in order. + * Overlaps with `mediaUris` but maintains explicit carousel semantics. + */ + slideUris?: string[]; + /** + * For reels, the video source URI. + */ + videoUri?: string; + /** The author's display name if extractable. */ + authorDisplayName?: string; + /** ISO 8601 parsed from the post timestamp element. */ + publishedAt?: string; +} diff --git a/packages/types/src/connector/pipeline.ts b/packages/types/src/connector/pipeline.ts new file mode 100644 index 0000000..3f9547e --- /dev/null +++ b/packages/types/src/connector/pipeline.ts @@ -0,0 +1,36 @@ +import { IResource } from '../core/resource'; + +/** + * Stage 1: Discovery. + * Represents a resource that is known to exist but whose full content has not been extracted. + */ +export interface IDiscoveredResource { + targetUri: string; + providerName: string; +} + +/** + * Stage 2: Extraction. + * Represents the raw data pulled from a source by a DOM Adapter or API client. + * This is an intermediate representation before domain normalization. + */ +export interface IRawSourceResource { + providerName: string; + sourceUri: string; + externalId?: string; + authorHandle?: string; + textContent?: string; + mediaUris: string[]; + publishedAt?: string; + metadata?: Record; +} + +/** + * Stage 3: Normalization. + * The standard interface every provider-specific connector must implement to + * map raw extracted data into the strict Domain Model. + */ +export interface IConnector { + readonly providerName: string; + normalize(raw: IRawSourceResource): Promise; +} diff --git a/packages/types/src/connector/strategy.ts b/packages/types/src/connector/strategy.ts new file mode 100644 index 0000000..f4da82b --- /dev/null +++ b/packages/types/src/connector/strategy.ts @@ -0,0 +1,30 @@ +/** + * Describes the applicability and confidence of an extraction strategy result. + */ +export interface IStrategyResult { + /** Whether this strategy was able to handle the input. */ + applicable: boolean; + /** + * Confidence score from 0.0 to 1.0 indicating reliability of the extracted data. + * Only meaningful when `applicable` is true. + */ + confidence: number; + /** The extracted data if applicable. */ + data?: T; + /** Human-readable explanation if the strategy was not applicable. */ + failureReason?: string; +} + +/** + * A single, independently executable extraction strategy. + * Strategies are tried in ordered chains; the first applicable result wins. + */ +export interface IExtractionStrategy { + /** Unique name for observability and debugging. */ + readonly strategyName: string; + /** + * Attempt to extract TOutput from the given input. + * Must never throw; failures are expressed via `IStrategyResult`. + */ + execute(input: TInput): IStrategyResult; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..13fce87 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,8194 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + .: + devDependencies: + '@changesets/cli': + specifier: ^2.27.1 + version: 2.31.0(@types/node@26.0.1) + '@commitlint/cli': + specifier: ^19.3.0 + version: 19.8.1(@types/node@26.0.1)(typescript@5.9.3) + '@commitlint/config-conventional': + specifier: ^19.2.2 + version: 19.8.1 + '@eslint/js': + specifier: ^9.5.0 + version: 9.39.4 + dependency-cruiser: + specifier: ^16.3.9 + version: 16.10.4 + eslint: + specifier: ^9.5.0 + version: 9.39.4(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.29.1 + version: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)) + husky: + specifier: ^9.0.11 + version: 9.1.7 + lint-staged: + specifier: ^15.2.7 + version: 15.5.2 + prettier: + specifier: ^3.3.2 + version: 3.8.4 + turbo: + specifier: ^2.0.4 + version: 2.10.0 + typescript: + specifier: ^5.4.5 + version: 5.9.3 + typescript-eslint: + specifier: ^7.13.0 + version: 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + + apps/extension: + dependencies: + '@knowledge-extractor/connector-instagram': + specifier: workspace:* + version: link:../../connectors/instagram + '@knowledge-extractor/shared': + specifier: workspace:* + version: link:../../packages/shared + '@knowledge-extractor/storage': + specifier: workspace:* + version: link:../../packages/storage + '@knowledge-extractor/types': + specifier: workspace:* + version: link:../../packages/types + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + devDependencies: + '@crxjs/vite-plugin': + specifier: ^2.0.0-beta.23 + version: 2.7.0(vite@5.4.21(@types/node@26.0.1)) + '@types/chrome': + specifier: ^0.0.268 + version: 0.0.268 + '@types/react': + specifier: ^18.3.3 + version: 18.3.31 + '@types/react-dom': + specifier: ^18.3.0 + version: 18.3.7(@types/react@18.3.31) + '@vitejs/plugin-react': + specifier: ^4.3.1 + version: 4.7.0(vite@5.4.21(@types/node@26.0.1)) + vite: + specifier: ^5.3.1 + version: 5.4.21(@types/node@26.0.1) + + connectors/instagram: + dependencies: + '@knowledge-extractor/shared': + specifier: workspace:* + version: link:../../packages/shared + '@knowledge-extractor/types': + specifier: workspace:* + version: link:../../packages/types + devDependencies: + '@vitest/coverage-v8': + specifier: ^2.1.9 + version: 2.1.9(vitest@2.1.9(@types/node@26.0.1)(jsdom@29.1.1)) + jsdom: + specifier: ^29.1.1 + version: 29.1.1 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@26.0.1)(jsdom@29.1.1) + + packages/shared: + dependencies: + '@knowledge-extractor/types': + specifier: workspace:* + version: link:../types + + packages/storage: + dependencies: + '@knowledge-extractor/shared': + specifier: workspace:* + version: link:../shared + '@knowledge-extractor/types': + specifier: workspace:* + version: link:../types + + packages/types: {} + +packages: + '@ampproject/remapping@2.3.0': + resolution: + { + integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==, + } + engines: { node: '>=6.0.0' } + + '@asamuzakjp/css-color@5.1.11': + resolution: + { + integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + '@asamuzakjp/dom-selector@7.1.1': + resolution: + { + integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + '@asamuzakjp/generational-cache@1.0.1': + resolution: + { + integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + '@asamuzakjp/nwsapi@2.3.9': + resolution: + { + integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==, + } + + '@babel/code-frame@7.29.7': + resolution: + { + integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==, + } + engines: { node: '>=6.9.0' } + + '@babel/compat-data@7.29.7': + resolution: + { + integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==, + } + engines: { node: '>=6.9.0' } + + '@babel/core@7.29.7': + resolution: + { + integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==, + } + engines: { node: '>=6.9.0' } + + '@babel/generator@7.29.7': + resolution: + { + integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-compilation-targets@7.29.7': + resolution: + { + integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-globals@7.29.7': + resolution: + { + integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-module-imports@7.29.7': + resolution: + { + integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-module-transforms@7.29.7': + resolution: + { + integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==, + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.29.7': + resolution: + { + integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-string-parser@7.29.7': + resolution: + { + integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-validator-identifier@7.29.7': + resolution: + { + integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==, + } + engines: { node: '>=6.9.0' } + + '@babel/helper-validator-option@7.29.7': + resolution: + { + integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==, + } + engines: { node: '>=6.9.0' } + + '@babel/helpers@7.29.7': + resolution: + { + integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==, + } + engines: { node: '>=6.9.0' } + + '@babel/parser@7.29.7': + resolution: + { + integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==, + } + engines: { node: '>=6.0.0' } + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: + { + integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==, + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: + { + integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==, + } + engines: { node: '>=6.9.0' } + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.7': + resolution: + { + integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==, + } + engines: { node: '>=6.9.0' } + + '@babel/template@7.29.7': + resolution: + { + integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==, + } + engines: { node: '>=6.9.0' } + + '@babel/traverse@7.29.7': + resolution: + { + integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==, + } + engines: { node: '>=6.9.0' } + + '@babel/types@7.29.7': + resolution: + { + integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==, + } + engines: { node: '>=6.9.0' } + + '@bcoe/v8-coverage@0.2.3': + resolution: + { + integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, + } + + '@bramus/specificity@2.4.2': + resolution: + { + integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==, + } + hasBin: true + + '@changesets/apply-release-plan@7.1.1': + resolution: + { + integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==, + } + + '@changesets/assemble-release-plan@6.0.10': + resolution: + { + integrity: sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==, + } + + '@changesets/changelog-git@0.2.1': + resolution: + { + integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==, + } + + '@changesets/cli@2.31.0': + resolution: + { + integrity: sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==, + } + hasBin: true + + '@changesets/config@3.1.4': + resolution: + { + integrity: sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==, + } + + '@changesets/errors@0.2.0': + resolution: + { + integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==, + } + + '@changesets/get-dependents-graph@2.1.4': + resolution: + { + integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==, + } + + '@changesets/get-release-plan@4.0.16': + resolution: + { + integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==, + } + + '@changesets/get-version-range-type@0.4.0': + resolution: + { + integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==, + } + + '@changesets/git@3.0.4': + resolution: + { + integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==, + } + + '@changesets/logger@0.1.1': + resolution: + { + integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==, + } + + '@changesets/parse@0.4.3': + resolution: + { + integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==, + } + + '@changesets/pre@2.0.2': + resolution: + { + integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==, + } + + '@changesets/read@0.6.7': + resolution: + { + integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==, + } + + '@changesets/should-skip-package@0.1.2': + resolution: + { + integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==, + } + + '@changesets/types@4.1.0': + resolution: + { + integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==, + } + + '@changesets/types@6.1.0': + resolution: + { + integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==, + } + + '@changesets/write@0.4.0': + resolution: + { + integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==, + } + + '@commitlint/cli@19.8.1': + resolution: + { + integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==, + } + engines: { node: '>=v18' } + hasBin: true + + '@commitlint/config-conventional@19.8.1': + resolution: + { + integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==, + } + engines: { node: '>=v18' } + + '@commitlint/config-validator@19.8.1': + resolution: + { + integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==, + } + engines: { node: '>=v18' } + + '@commitlint/ensure@19.8.1': + resolution: + { + integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==, + } + engines: { node: '>=v18' } + + '@commitlint/execute-rule@19.8.1': + resolution: + { + integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==, + } + engines: { node: '>=v18' } + + '@commitlint/format@19.8.1': + resolution: + { + integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==, + } + engines: { node: '>=v18' } + + '@commitlint/is-ignored@19.8.1': + resolution: + { + integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==, + } + engines: { node: '>=v18' } + + '@commitlint/lint@19.8.1': + resolution: + { + integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==, + } + engines: { node: '>=v18' } + + '@commitlint/load@19.8.1': + resolution: + { + integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==, + } + engines: { node: '>=v18' } + + '@commitlint/message@19.8.1': + resolution: + { + integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==, + } + engines: { node: '>=v18' } + + '@commitlint/parse@19.8.1': + resolution: + { + integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==, + } + engines: { node: '>=v18' } + + '@commitlint/read@19.8.1': + resolution: + { + integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==, + } + engines: { node: '>=v18' } + + '@commitlint/resolve-extends@19.8.1': + resolution: + { + integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==, + } + engines: { node: '>=v18' } + + '@commitlint/rules@19.8.1': + resolution: + { + integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==, + } + engines: { node: '>=v18' } + + '@commitlint/to-lines@19.8.1': + resolution: + { + integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==, + } + engines: { node: '>=v18' } + + '@commitlint/top-level@19.8.1': + resolution: + { + integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==, + } + engines: { node: '>=v18' } + + '@commitlint/types@19.8.1': + resolution: + { + integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==, + } + engines: { node: '>=v18' } + + '@crxjs/vite-plugin@2.7.0': + resolution: + { + integrity: sha512-NN98fUgJOEiVBshELJnYCW54+K2Yy067++/K+RdxclHsyG08ea+Em3lJJTubtPTCl2bECyp4+K69oT+izilnNw==, + } + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@csstools/color-helpers@6.1.0': + resolution: + { + integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==, + } + engines: { node: '>=20.19.0' } + + '@csstools/css-calc@3.2.1': + resolution: + { + integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==, + } + engines: { node: '>=20.19.0' } + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.1.9': + resolution: + { + integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==, + } + engines: { node: '>=20.19.0' } + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: + { + integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==, + } + engines: { node: '>=20.19.0' } + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.5': + resolution: + { + integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==, + } + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: + { + integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==, + } + engines: { node: '>=20.19.0' } + + '@esbuild/aix-ppc64@0.21.5': + resolution: + { + integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==, + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: + { + integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==, + } + engines: { node: '>=12' } + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: + { + integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==, + } + engines: { node: '>=12' } + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: + { + integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: + { + integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==, + } + engines: { node: '>=12' } + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: + { + integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: + { + integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==, + } + engines: { node: '>=12' } + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: + { + integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: + { + integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==, + } + engines: { node: '>=12' } + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: + { + integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==, + } + engines: { node: '>=12' } + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: + { + integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==, + } + engines: { node: '>=12' } + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: + { + integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==, + } + engines: { node: '>=12' } + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: + { + integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==, + } + engines: { node: '>=12' } + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: + { + integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==, + } + engines: { node: '>=12' } + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: + { + integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==, + } + engines: { node: '>=12' } + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: + { + integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==, + } + engines: { node: '>=12' } + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: + { + integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: + { + integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: + { + integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: + { + integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: + { + integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==, + } + engines: { node: '>=12' } + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: + { + integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==, + } + engines: { node: '>=12' } + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: + { + integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==, + } + engines: { node: '>=12' } + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: + { + integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: + { + integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, + } + engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + + '@eslint/config-array@0.21.2': + resolution: + { + integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/config-helpers@0.4.2': + resolution: + { + integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/core@0.17.0': + resolution: + { + integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/eslintrc@3.3.5': + resolution: + { + integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/js@9.39.4': + resolution: + { + integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/object-schema@2.1.7': + resolution: + { + integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@eslint/plugin-kit@0.4.1': + resolution: + { + integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + '@exodus/bytes@1.15.1': + resolution: + { + integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + + '@humanfs/core@0.19.2': + resolution: + { + integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==, + } + engines: { node: '>=18.18.0' } + + '@humanfs/node@0.16.8': + resolution: + { + integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==, + } + engines: { node: '>=18.18.0' } + + '@humanfs/types@0.15.0': + resolution: + { + integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==, + } + engines: { node: '>=18.18.0' } + + '@humanwhocodes/module-importer@1.0.1': + resolution: + { + integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, + } + engines: { node: '>=12.22' } + + '@humanwhocodes/retry@0.4.3': + resolution: + { + integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, + } + engines: { node: '>=18.18' } + + '@inquirer/external-editor@1.0.3': + resolution: + { + integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==, + } + engines: { node: '>=18' } + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@isaacs/cliui@8.0.2': + resolution: + { + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + } + engines: { node: '>=12' } + + '@istanbuljs/schema@0.1.6': + resolution: + { + integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==, + } + engines: { node: '>=8' } + + '@jridgewell/gen-mapping@0.3.13': + resolution: + { + integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, + } + + '@jridgewell/remapping@2.3.5': + resolution: + { + integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, + } + + '@jridgewell/resolve-uri@3.1.2': + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, + } + engines: { node: '>=6.0.0' } + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: + { + integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, + } + + '@jridgewell/trace-mapping@0.3.31': + resolution: + { + integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, + } + + '@manypkg/find-root@1.1.0': + resolution: + { + integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==, + } + + '@manypkg/get-packages@1.1.3': + resolution: + { + integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==, + } + + '@nodelib/fs.scandir@2.1.5': + resolution: + { + integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, + } + engines: { node: '>= 8' } + + '@nodelib/fs.stat@2.0.5': + resolution: + { + integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, + } + engines: { node: '>= 8' } + + '@nodelib/fs.walk@1.2.8': + resolution: + { + integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, + } + engines: { node: '>= 8' } + + '@pkgjs/parseargs@0.11.0': + resolution: + { + integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, + } + engines: { node: '>=14' } + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: + { + integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==, + } + + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: + { + integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==, + } + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: + { + integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==, + } + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: + { + integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==, + } + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: + { + integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==, + } + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: + { + integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==, + } + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: + { + integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==, + } + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: + { + integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==, + } + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: + { + integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==, + } + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: + { + integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==, + } + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: + { + integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==, + } + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: + { + integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==, + } + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: + { + integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==, + } + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: + { + integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==, + } + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: + { + integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==, + } + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: + { + integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==, + } + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: + { + integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==, + } + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: + { + integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==, + } + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: + { + integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==, + } + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: + { + integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==, + } + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: + { + integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==, + } + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: + { + integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==, + } + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: + { + integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==, + } + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: + { + integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==, + } + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: + { + integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==, + } + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: + { + integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==, + } + cpu: [x64] + os: [win32] + + '@rtsao/scc@1.1.0': + resolution: + { + integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==, + } + + '@turbo/darwin-64@2.10.0': + resolution: + { + integrity: sha512-EwvHThXzpY0KGd1/NAmuewI5D+aVa3Rl/OlxE36yfjUKb/+ySrfJrSlEFt8aD1OXwnnaHnQnPKHFndor0Zxlsg==, + } + cpu: [x64] + os: [darwin] + + '@turbo/darwin-arm64@2.10.0': + resolution: + { + integrity: sha512-9d2fTyyG0lf5Wq1bwJA9qUaeecViMkLcdctWaMMmCkxZ/JqypmqOwK3W6vmejeKVgkr06gSoiX8bD+xN5Jpxcg==, + } + cpu: [arm64] + os: [darwin] + + '@turbo/linux-64@2.10.0': + resolution: + { + integrity: sha512-sZBtjMuufitanjzi6UssoUpJMnnPlLMcdcJj3m3ptNsSq31Xh7MnjhwA5nWvLDTfEFg8GPcbYFXMo8vSdKRfqQ==, + } + cpu: [x64] + os: [linux] + + '@turbo/linux-arm64@2.10.0': + resolution: + { + integrity: sha512-vkq/Z8R+1DQ+kifWFa810IjRy2NNBVvha3cg9sWA3nFh6nnGrHSMnnJKrzH7c/No9kq4Jb55Ru44YKsCSBgrKg==, + } + cpu: [arm64] + os: [linux] + + '@turbo/windows-64@2.10.0': + resolution: + { + integrity: sha512-CRUEguLWxFQHptYZS7HjPhNhAFawfea07iR+xAQ5e4klgLrPCMdexBkXwSCwOxqTFknJ7RZFN3gOaADsw+Gttg==, + } + cpu: [x64] + os: [win32] + + '@turbo/windows-arm64@2.10.0': + resolution: + { + integrity: sha512-dVHGaf9F8twzgibcBqKoADT/LLqf9++jDb+hq/LPWWaOmRpp4M+/pVOm7vy4z9D++xg8eaxWLT0+wQxFwhYu9A==, + } + cpu: [arm64] + os: [win32] + + '@types/babel__core@7.20.5': + resolution: + { + integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==, + } + + '@types/babel__generator@7.27.0': + resolution: + { + integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==, + } + + '@types/babel__template@7.4.4': + resolution: + { + integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==, + } + + '@types/babel__traverse@7.28.0': + resolution: + { + integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==, + } + + '@types/chrome@0.0.268': + resolution: + { + integrity: sha512-7N1QH9buudSJ7sI8Pe4mBHJr5oZ48s0hcanI9w3wgijAlv1OZNUZve9JR4x42dn5lJ5Sm87V1JNfnoh10EnQlA==, + } + + '@types/conventional-commits-parser@5.0.2': + resolution: + { + integrity: sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g==, + } + + '@types/estree@1.0.9': + resolution: + { + integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==, + } + + '@types/filesystem@0.0.36': + resolution: + { + integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==, + } + + '@types/filewriter@0.0.33': + resolution: + { + integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==, + } + + '@types/har-format@1.2.16': + resolution: + { + integrity: sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==, + } + + '@types/json-schema@7.0.15': + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, + } + + '@types/json5@0.0.29': + resolution: + { + integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, + } + + '@types/node@12.20.55': + resolution: + { + integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==, + } + + '@types/node@26.0.1': + resolution: + { + integrity: sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==, + } + + '@types/prop-types@15.7.15': + resolution: + { + integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==, + } + + '@types/react-dom@18.3.7': + resolution: + { + integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==, + } + peerDependencies: + '@types/react': ^18.0.0 + + '@types/react@18.3.31': + resolution: + { + integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==, + } + + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: + { + integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.18.0': + resolution: + { + integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.18.0': + resolution: + { + integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + + '@typescript-eslint/type-utils@7.18.0': + resolution: + { + integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.18.0': + resolution: + { + integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: + { + integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.18.0': + resolution: + { + integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: + { + integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + + '@vitejs/plugin-react@4.7.0': + resolution: + { + integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==, + } + engines: { node: ^14.18.0 || >=16.0.0 } + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@vitest/coverage-v8@2.1.9': + resolution: + { + integrity: sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==, + } + peerDependencies: + '@vitest/browser': 2.1.9 + vitest: 2.1.9 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@2.1.9': + resolution: + { + integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==, + } + + '@vitest/mocker@2.1.9': + resolution: + { + integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==, + } + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.9': + resolution: + { + integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==, + } + + '@vitest/runner@2.1.9': + resolution: + { + integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==, + } + + '@vitest/snapshot@2.1.9': + resolution: + { + integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==, + } + + '@vitest/spy@2.1.9': + resolution: + { + integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==, + } + + '@vitest/utils@2.1.9': + resolution: + { + integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==, + } + + '@webcomponents/custom-elements@1.6.0': + resolution: + { + integrity: sha512-CqTpxOlUCPWRNUPZDxT5v2NnHXA4oox612iUGnmTUGQFhZ1Gkj8kirtl/2wcF6MqX7+PqqicZzOCBKKfIn0dww==, + } + + JSONStream@1.3.5: + resolution: + { + integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==, + } + hasBin: true + + acorn-jsx-walk@2.0.0: + resolution: + { + integrity: sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==, + } + + acorn-jsx@5.3.2: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + } + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-loose@8.5.2: + resolution: + { + integrity: sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A==, + } + engines: { node: '>=0.4.0' } + + acorn-walk@8.3.5: + resolution: + { + integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==, + } + engines: { node: '>=0.4.0' } + + acorn@8.17.0: + resolution: + { + integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==, + } + engines: { node: '>=0.4.0' } + hasBin: true + + ajv@6.15.0: + resolution: + { + integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==, + } + + ajv@8.20.0: + resolution: + { + integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==, + } + + ansi-colors@4.1.3: + resolution: + { + integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, + } + engines: { node: '>=6' } + + ansi-escapes@7.3.0: + resolution: + { + integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==, + } + engines: { node: '>=18' } + + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: '>=8' } + + ansi-regex@6.2.2: + resolution: + { + integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, + } + engines: { node: '>=12' } + + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: '>=8' } + + ansi-styles@6.2.3: + resolution: + { + integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, + } + engines: { node: '>=12' } + + argparse@1.0.10: + resolution: + { + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, + } + + argparse@2.0.1: + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, + } + + array-buffer-byte-length@1.0.2: + resolution: + { + integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==, + } + engines: { node: '>= 0.4' } + + array-ify@1.0.0: + resolution: + { + integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==, + } + + array-includes@3.1.9: + resolution: + { + integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==, + } + engines: { node: '>= 0.4' } + + array-union@2.1.0: + resolution: + { + integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, + } + engines: { node: '>=8' } + + array.prototype.findlastindex@1.2.6: + resolution: + { + integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==, + } + engines: { node: '>= 0.4' } + + array.prototype.flat@1.3.3: + resolution: + { + integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==, + } + engines: { node: '>= 0.4' } + + array.prototype.flatmap@1.3.3: + resolution: + { + integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==, + } + engines: { node: '>= 0.4' } + + arraybuffer.prototype.slice@1.0.4: + resolution: + { + integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==, + } + engines: { node: '>= 0.4' } + + assertion-error@2.0.1: + resolution: + { + integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, + } + engines: { node: '>=12' } + + async-function@1.0.0: + resolution: + { + integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==, + } + engines: { node: '>= 0.4' } + + available-typed-arrays@1.0.7: + resolution: + { + integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==, + } + engines: { node: '>= 0.4' } + + balanced-match@1.0.2: + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } + + balanced-match@4.0.4: + resolution: + { + integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, + } + engines: { node: 18 || 20 || >=22 } + + baseline-browser-mapping@2.10.40: + resolution: + { + integrity: sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==, + } + engines: { node: '>=6.0.0' } + hasBin: true + + better-path-resolve@1.0.0: + resolution: + { + integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==, + } + engines: { node: '>=4' } + + bidi-js@1.0.3: + resolution: + { + integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==, + } + + boolbase@1.0.0: + resolution: + { + integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, + } + + brace-expansion@1.1.15: + resolution: + { + integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==, + } + + brace-expansion@2.1.1: + resolution: + { + integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==, + } + + brace-expansion@5.0.6: + resolution: + { + integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==, + } + engines: { node: 18 || 20 || >=22 } + + braces@3.0.3: + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, + } + engines: { node: '>=8' } + + browserslist@4.28.4: + resolution: + { + integrity: sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + + cac@6.7.14: + resolution: + { + integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==, + } + engines: { node: '>=8' } + + call-bind-apply-helpers@1.0.2: + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, + } + engines: { node: '>= 0.4' } + + call-bind@1.0.9: + resolution: + { + integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==, + } + engines: { node: '>= 0.4' } + + call-bound@1.0.4: + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, + } + engines: { node: '>= 0.4' } + + callsites@3.1.0: + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, + } + engines: { node: '>=6' } + + caniuse-lite@1.0.30001799: + resolution: + { + integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==, + } + + chai@5.3.3: + resolution: + { + integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==, + } + engines: { node: '>=18' } + + chalk@4.1.2: + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: '>=10' } + + chalk@5.6.2: + resolution: + { + integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + + chardet@2.2.0: + resolution: + { + integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==, + } + + check-error@2.1.3: + resolution: + { + integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==, + } + engines: { node: '>= 16' } + + cli-cursor@5.0.0: + resolution: + { + integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==, + } + engines: { node: '>=18' } + + cli-truncate@4.0.0: + resolution: + { + integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==, + } + engines: { node: '>=18' } + + cliui@8.0.1: + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, + } + engines: { node: '>=12' } + + color-convert@2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: '>=7.0.0' } + + color-name@1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } + + colorette@2.0.20: + resolution: + { + integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, + } + + commander@13.1.0: + resolution: + { + integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==, + } + engines: { node: '>=18' } + + compare-func@2.0.0: + resolution: + { + integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==, + } + + concat-map@0.0.1: + resolution: + { + integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==, + } + + conventional-changelog-angular@7.0.0: + resolution: + { + integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==, + } + engines: { node: '>=16' } + + conventional-changelog-conventionalcommits@7.0.2: + resolution: + { + integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==, + } + engines: { node: '>=16' } + + conventional-commits-parser@5.0.0: + resolution: + { + integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==, + } + engines: { node: '>=16' } + hasBin: true + + convert-source-map@1.9.0: + resolution: + { + integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==, + } + + convert-source-map@2.0.0: + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, + } + + cosmiconfig-typescript-loader@6.3.0: + resolution: + { + integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==, + } + engines: { node: '>=v18' } + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@9.0.2: + resolution: + { + integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==, + } + engines: { node: '>=14' } + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, + } + engines: { node: '>= 8' } + + css-select@5.2.2: + resolution: + { + integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, + } + + css-tree@3.2.1: + resolution: + { + integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==, + } + engines: { node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0 } + + css-what@6.2.2: + resolution: + { + integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, + } + engines: { node: '>= 6' } + + csstype@3.2.3: + resolution: + { + integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, + } + + dargs@8.1.0: + resolution: + { + integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==, + } + engines: { node: '>=12' } + + data-urls@7.0.0: + resolution: + { + integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + data-view-buffer@1.0.2: + resolution: + { + integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==, + } + engines: { node: '>= 0.4' } + + data-view-byte-length@1.0.2: + resolution: + { + integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==, + } + engines: { node: '>= 0.4' } + + data-view-byte-offset@1.0.1: + resolution: + { + integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==, + } + engines: { node: '>= 0.4' } + + debug@3.2.7: + resolution: + { + integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, + } + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: + { + integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, + } + engines: { node: '>=6.0' } + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: + { + integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==, + } + + deep-eql@5.0.2: + resolution: + { + integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, + } + engines: { node: '>=6' } + + deep-is@0.1.4: + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, + } + + define-data-property@1.1.4: + resolution: + { + integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, + } + engines: { node: '>= 0.4' } + + define-properties@1.2.1: + resolution: + { + integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, + } + engines: { node: '>= 0.4' } + + dependency-cruiser@16.10.4: + resolution: + { + integrity: sha512-hrxVOjIm8idZ9ZVDGSyyG3SHiNcEUPhL6RTEmO/3wfQWLepH5pA3nuDMMrcJ1DkZztFA7xg3tk8OVO+MmwwH9w==, + } + engines: { node: ^18.17||>=20 } + hasBin: true + + detect-indent@6.1.0: + resolution: + { + integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==, + } + engines: { node: '>=8' } + + dir-glob@3.0.1: + resolution: + { + integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, + } + engines: { node: '>=8' } + + doctrine@2.1.0: + resolution: + { + integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, + } + engines: { node: '>=0.10.0' } + + dom-serializer@2.0.0: + resolution: + { + integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, + } + + domelementtype@2.3.0: + resolution: + { + integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, + } + + domhandler@5.0.3: + resolution: + { + integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, + } + engines: { node: '>= 4' } + + domutils@3.2.2: + resolution: + { + integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, + } + + dot-prop@5.3.0: + resolution: + { + integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==, + } + engines: { node: '>=8' } + + dunder-proto@1.0.1: + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: '>= 0.4' } + + eastasianwidth@0.2.0: + resolution: + { + integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, + } + + electron-to-chromium@1.5.379: + resolution: + { + integrity: sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA==, + } + + emoji-regex@10.6.0: + resolution: + { + integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==, + } + + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + emoji-regex@9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + + enhanced-resolve@5.24.1: + resolution: + { + integrity: sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==, + } + engines: { node: '>=10.13.0' } + + enquirer@2.4.1: + resolution: + { + integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==, + } + engines: { node: '>=8.6' } + + entities@4.5.0: + resolution: + { + integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, + } + engines: { node: '>=0.12' } + + entities@8.0.0: + resolution: + { + integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==, + } + engines: { node: '>=20.19.0' } + + env-paths@2.2.1: + resolution: + { + integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==, + } + engines: { node: '>=6' } + + environment@1.1.0: + resolution: + { + integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==, + } + engines: { node: '>=18' } + + error-ex@1.3.4: + resolution: + { + integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, + } + + es-abstract-get@1.0.0: + resolution: + { + integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==, + } + engines: { node: '>= 0.4' } + + es-abstract@1.24.2: + resolution: + { + integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==, + } + engines: { node: '>= 0.4' } + + es-define-property@1.0.1: + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, + } + engines: { node: '>= 0.4' } + + es-errors@1.3.0: + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, + } + engines: { node: '>= 0.4' } + + es-module-lexer@0.10.5: + resolution: + { + integrity: sha512-+7IwY/kiGAacQfY+YBhKMvEmyAJnw5grTUgjG85Pe7vcUI/6b7pZjZG8nQ7+48YhzEAEqrEgD2dCz/JIK+AYvw==, + } + + es-module-lexer@1.7.0: + resolution: + { + integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, + } + + es-object-atoms@1.1.2: + resolution: + { + integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==, + } + engines: { node: '>= 0.4' } + + es-set-tostringtag@2.1.0: + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, + } + engines: { node: '>= 0.4' } + + es-shim-unscopables@1.1.0: + resolution: + { + integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==, + } + engines: { node: '>= 0.4' } + + es-to-primitive@1.3.4: + resolution: + { + integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==, + } + engines: { node: '>= 0.4' } + + esbuild@0.21.5: + resolution: + { + integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==, + } + engines: { node: '>=12' } + hasBin: true + + escalade@3.2.0: + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, + } + engines: { node: '>=6' } + + escape-string-regexp@4.0.0: + resolution: + { + integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, + } + engines: { node: '>=10' } + + eslint-import-resolver-node@0.3.10: + resolution: + { + integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==, + } + + eslint-module-utils@2.13.0: + resolution: + { + integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==, + } + engines: { node: '>=4' } + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.32.0: + resolution: + { + integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==, + } + engines: { node: '>=4' } + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-scope@8.4.0: + resolution: + { + integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + eslint-visitor-keys@3.4.3: + resolution: + { + integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + eslint-visitor-keys@4.2.1: + resolution: + { + integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + eslint@9.39.4: + resolution: + { + integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: + { + integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + esprima@4.0.1: + resolution: + { + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, + } + engines: { node: '>=4' } + hasBin: true + + esquery@1.7.0: + resolution: + { + integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, + } + engines: { node: '>=0.10' } + + esrecurse@4.3.0: + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, + } + engines: { node: '>=4.0' } + + estraverse@5.3.0: + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: '>=4.0' } + + estree-walker@3.0.3: + resolution: + { + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, + } + + esutils@2.0.3: + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, + } + engines: { node: '>=0.10.0' } + + eventemitter3@5.0.4: + resolution: + { + integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==, + } + + execa@8.0.1: + resolution: + { + integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==, + } + engines: { node: '>=16.17' } + + expect-type@1.4.0: + resolution: + { + integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==, + } + engines: { node: '>=12.0.0' } + + extendable-error@0.1.7: + resolution: + { + integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==, + } + + fast-deep-equal@3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } + + fast-glob@3.3.3: + resolution: + { + integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, + } + engines: { node: '>=8.6.0' } + + fast-json-stable-stringify@2.1.0: + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, + } + + fast-levenshtein@2.0.6: + resolution: + { + integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, + } + + fast-uri@3.1.2: + resolution: + { + integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==, + } + + fastq@1.20.1: + resolution: + { + integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, + } + + fdir@6.5.0: + resolution: + { + integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, + } + engines: { node: '>=12.0.0' } + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: + { + integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, + } + engines: { node: '>=16.0.0' } + + fill-range@7.1.1: + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, + } + engines: { node: '>=8' } + + find-up@4.1.0: + resolution: + { + integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, + } + engines: { node: '>=8' } + + find-up@5.0.0: + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, + } + engines: { node: '>=10' } + + find-up@7.0.0: + resolution: + { + integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==, + } + engines: { node: '>=18' } + + flat-cache@4.0.1: + resolution: + { + integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, + } + engines: { node: '>=16' } + + flatted@3.4.2: + resolution: + { + integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==, + } + + for-each@0.3.5: + resolution: + { + integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==, + } + engines: { node: '>= 0.4' } + + foreground-child@3.3.1: + resolution: + { + integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, + } + engines: { node: '>=14' } + + fs-extra@10.1.0: + resolution: + { + integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==, + } + engines: { node: '>=12' } + + fs-extra@7.0.1: + resolution: + { + integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==, + } + engines: { node: '>=6 <7 || >=8' } + + fs-extra@8.1.0: + resolution: + { + integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==, + } + engines: { node: '>=6 <7 || >=8' } + + fsevents@2.3.3: + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + function-bind@1.1.2: + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } + + function.prototype.name@1.2.0: + resolution: + { + integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==, + } + engines: { node: '>= 0.4' } + + functions-have-names@1.2.3: + resolution: + { + integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, + } + + generator-function@2.0.1: + resolution: + { + integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==, + } + engines: { node: '>= 0.4' } + + gensync@1.0.0-beta.2: + resolution: + { + integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, + } + engines: { node: '>=6.9.0' } + + get-caller-file@2.0.5: + resolution: + { + integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, + } + engines: { node: 6.* || 8.* || >= 10.* } + + get-east-asian-width@1.6.0: + resolution: + { + integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==, + } + engines: { node: '>=18' } + + get-intrinsic@1.3.0: + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, + } + engines: { node: '>= 0.4' } + + get-proto@1.0.1: + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, + } + engines: { node: '>= 0.4' } + + get-stream@8.0.1: + resolution: + { + integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==, + } + engines: { node: '>=16' } + + get-symbol-description@1.1.0: + resolution: + { + integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==, + } + engines: { node: '>= 0.4' } + + git-raw-commits@4.0.0: + resolution: + { + integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==, + } + engines: { node: '>=16' } + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. + hasBin: true + + glob-parent@5.1.2: + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: '>= 6' } + + glob-parent@6.0.2: + resolution: + { + integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, + } + engines: { node: '>=10.13.0' } + + glob@10.5.0: + resolution: + { + integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==, + } + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + global-directory@4.0.1: + resolution: + { + integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==, + } + engines: { node: '>=18' } + + globals@14.0.0: + resolution: + { + integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==, + } + engines: { node: '>=18' } + + globalthis@1.0.4: + resolution: + { + integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==, + } + engines: { node: '>= 0.4' } + + globby@11.1.0: + resolution: + { + integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, + } + engines: { node: '>=10' } + + gopd@1.2.0: + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, + } + engines: { node: '>= 0.4' } + + graceful-fs@4.2.11: + resolution: + { + integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, + } + + graphemer@1.4.0: + resolution: + { + integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==, + } + + has-bigints@1.1.0: + resolution: + { + integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==, + } + engines: { node: '>= 0.4' } + + has-flag@4.0.0: + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, + } + engines: { node: '>=8' } + + has-property-descriptors@1.0.2: + resolution: + { + integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, + } + + has-proto@1.2.0: + resolution: + { + integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==, + } + engines: { node: '>= 0.4' } + + has-symbols@1.1.0: + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, + } + engines: { node: '>= 0.4' } + + has-tostringtag@1.0.2: + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, + } + engines: { node: '>= 0.4' } + + hasown@2.0.4: + resolution: + { + integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==, + } + engines: { node: '>= 0.4' } + + he@1.2.0: + resolution: + { + integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==, + } + hasBin: true + + html-encoding-sniffer@6.0.0: + resolution: + { + integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + html-escaper@2.0.2: + resolution: + { + integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, + } + + human-id@4.2.0: + resolution: + { + integrity: sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==, + } + hasBin: true + + human-signals@5.0.0: + resolution: + { + integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==, + } + engines: { node: '>=16.17.0' } + + husky@9.1.7: + resolution: + { + integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==, + } + engines: { node: '>=18' } + hasBin: true + + iconv-lite@0.7.2: + resolution: + { + integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==, + } + engines: { node: '>=0.10.0' } + + ignore@5.3.2: + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, + } + engines: { node: '>= 4' } + + ignore@7.0.5: + resolution: + { + integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, + } + engines: { node: '>= 4' } + + import-fresh@3.3.1: + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, + } + engines: { node: '>=6' } + + import-meta-resolve@4.2.0: + resolution: + { + integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==, + } + + imurmurhash@0.1.4: + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, + } + engines: { node: '>=0.8.19' } + + ini@4.1.1: + resolution: + { + integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==, + } + engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + + internal-slot@1.1.0: + resolution: + { + integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==, + } + engines: { node: '>= 0.4' } + + interpret@3.1.1: + resolution: + { + integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==, + } + engines: { node: '>=10.13.0' } + + is-array-buffer@3.0.5: + resolution: + { + integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==, + } + engines: { node: '>= 0.4' } + + is-arrayish@0.2.1: + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, + } + + is-async-function@2.1.1: + resolution: + { + integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==, + } + engines: { node: '>= 0.4' } + + is-bigint@1.1.0: + resolution: + { + integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==, + } + engines: { node: '>= 0.4' } + + is-boolean-object@1.2.2: + resolution: + { + integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==, + } + engines: { node: '>= 0.4' } + + is-callable@1.2.7: + resolution: + { + integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==, + } + engines: { node: '>= 0.4' } + + is-core-module@2.16.2: + resolution: + { + integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==, + } + engines: { node: '>= 0.4' } + + is-data-view@1.0.2: + resolution: + { + integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==, + } + engines: { node: '>= 0.4' } + + is-date-object@1.1.0: + resolution: + { + integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==, + } + engines: { node: '>= 0.4' } + + is-document.all@1.0.0: + resolution: + { + integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==, + } + engines: { node: '>= 0.4' } + + is-extglob@2.1.1: + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: '>=0.10.0' } + + is-finalizationregistry@1.1.1: + resolution: + { + integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==, + } + engines: { node: '>= 0.4' } + + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: '>=8' } + + is-fullwidth-code-point@4.0.0: + resolution: + { + integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==, + } + engines: { node: '>=12' } + + is-fullwidth-code-point@5.1.0: + resolution: + { + integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==, + } + engines: { node: '>=18' } + + is-generator-function@1.1.2: + resolution: + { + integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==, + } + engines: { node: '>= 0.4' } + + is-glob@4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: '>=0.10.0' } + + is-installed-globally@1.0.0: + resolution: + { + integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==, + } + engines: { node: '>=18' } + + is-map@2.0.3: + resolution: + { + integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==, + } + engines: { node: '>= 0.4' } + + is-negative-zero@2.0.3: + resolution: + { + integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==, + } + engines: { node: '>= 0.4' } + + is-number-object@1.1.1: + resolution: + { + integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==, + } + engines: { node: '>= 0.4' } + + is-number@7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: '>=0.12.0' } + + is-obj@2.0.0: + resolution: + { + integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==, + } + engines: { node: '>=8' } + + is-path-inside@4.0.0: + resolution: + { + integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==, + } + engines: { node: '>=12' } + + is-potential-custom-element-name@1.0.1: + resolution: + { + integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==, + } + + is-regex@1.2.1: + resolution: + { + integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, + } + engines: { node: '>= 0.4' } + + is-set@2.0.3: + resolution: + { + integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==, + } + engines: { node: '>= 0.4' } + + is-shared-array-buffer@1.0.4: + resolution: + { + integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==, + } + engines: { node: '>= 0.4' } + + is-stream@3.0.0: + resolution: + { + integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + is-string@1.1.1: + resolution: + { + integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==, + } + engines: { node: '>= 0.4' } + + is-subdir@1.2.0: + resolution: + { + integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==, + } + engines: { node: '>=4' } + + is-symbol@1.1.1: + resolution: + { + integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==, + } + engines: { node: '>= 0.4' } + + is-text-path@2.0.0: + resolution: + { + integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==, + } + engines: { node: '>=8' } + + is-typed-array@1.1.15: + resolution: + { + integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, + } + engines: { node: '>= 0.4' } + + is-weakmap@2.0.2: + resolution: + { + integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==, + } + engines: { node: '>= 0.4' } + + is-weakref@1.1.1: + resolution: + { + integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==, + } + engines: { node: '>= 0.4' } + + is-weakset@2.0.4: + resolution: + { + integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==, + } + engines: { node: '>= 0.4' } + + is-windows@1.0.2: + resolution: + { + integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==, + } + engines: { node: '>=0.10.0' } + + isarray@2.0.5: + resolution: + { + integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, + } + + isexe@2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + + istanbul-lib-coverage@3.2.2: + resolution: + { + integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, + } + engines: { node: '>=8' } + + istanbul-lib-report@3.0.1: + resolution: + { + integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, + } + engines: { node: '>=10' } + + istanbul-lib-source-maps@5.0.6: + resolution: + { + integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==, + } + engines: { node: '>=10' } + + istanbul-reports@3.2.0: + resolution: + { + integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, + } + engines: { node: '>=8' } + + jackspeak@3.4.3: + resolution: + { + integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, + } + + jiti@2.6.1: + resolution: + { + integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==, + } + hasBin: true + + js-tokens@4.0.0: + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } + + js-yaml@3.14.2: + resolution: + { + integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==, + } + hasBin: true + + js-yaml@4.2.0: + resolution: + { + integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==, + } + hasBin: true + + jsdom@29.1.1: + resolution: + { + integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==, + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24.0.0 } + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, + } + engines: { node: '>=6' } + hasBin: true + + json-buffer@3.0.1: + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, + } + + json-parse-even-better-errors@2.3.1: + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } + + json-schema-traverse@0.4.1: + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, + } + + json-schema-traverse@1.0.0: + resolution: + { + integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, + } + + json-stable-stringify-without-jsonify@1.0.1: + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, + } + + json5@1.0.2: + resolution: + { + integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==, + } + hasBin: true + + json5@2.2.3: + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, + } + engines: { node: '>=6' } + hasBin: true + + jsonfile@4.0.0: + resolution: + { + integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==, + } + + jsonfile@6.2.1: + resolution: + { + integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==, + } + + jsonparse@1.3.1: + resolution: + { + integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==, + } + engines: { '0': node >= 0.2.0 } + + keyv@4.5.4: + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, + } + + kleur@3.0.3: + resolution: + { + integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==, + } + engines: { node: '>=6' } + + levn@0.4.1: + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, + } + engines: { node: '>= 0.8.0' } + + lilconfig@3.1.3: + resolution: + { + integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==, + } + engines: { node: '>=14' } + + lines-and-columns@1.2.4: + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + } + + lint-staged@15.5.2: + resolution: + { + integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==, + } + engines: { node: '>=18.12.0' } + hasBin: true + + listr2@8.3.3: + resolution: + { + integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==, + } + engines: { node: '>=18.0.0' } + + locate-path@5.0.0: + resolution: + { + integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, + } + engines: { node: '>=8' } + + locate-path@6.0.0: + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, + } + engines: { node: '>=10' } + + locate-path@7.2.0: + resolution: + { + integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + lodash.camelcase@4.3.0: + resolution: + { + integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==, + } + + lodash.isplainobject@4.0.6: + resolution: + { + integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==, + } + + lodash.kebabcase@4.1.1: + resolution: + { + integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==, + } + + lodash.merge@4.6.2: + resolution: + { + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, + } + + lodash.mergewith@4.6.2: + resolution: + { + integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==, + } + + lodash.snakecase@4.1.1: + resolution: + { + integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==, + } + + lodash.startcase@4.4.0: + resolution: + { + integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==, + } + + lodash.uniq@4.5.0: + resolution: + { + integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==, + } + + lodash.upperfirst@4.3.1: + resolution: + { + integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==, + } + + log-update@6.1.0: + resolution: + { + integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==, + } + engines: { node: '>=18' } + + loose-envify@1.4.0: + resolution: + { + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, + } + hasBin: true + + loupe@3.2.1: + resolution: + { + integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==, + } + + lru-cache@10.4.3: + resolution: + { + integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, + } + + lru-cache@11.5.1: + resolution: + { + integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==, + } + engines: { node: 20 || >=22 } + + lru-cache@5.1.1: + resolution: + { + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, + } + + magic-string@0.30.21: + resolution: + { + integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, + } + + magicast@0.3.5: + resolution: + { + integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==, + } + + make-dir@4.0.0: + resolution: + { + integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==, + } + engines: { node: '>=10' } + + math-intrinsics@1.1.0: + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: '>= 0.4' } + + mdn-data@2.27.1: + resolution: + { + integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==, + } + + memoize@10.2.0: + resolution: + { + integrity: sha512-DeC6b7QBrZsRs3Y02A6A7lQyzFbsQbqgjI6UW0GigGWV+u1s25TycMr0XHZE4cJce7rY/vyw2ctMQqfDkIhUEA==, + } + engines: { node: '>=18' } + + meow@12.1.1: + resolution: + { + integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==, + } + engines: { node: '>=16.10' } + + merge-stream@2.0.0: + resolution: + { + integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, + } + + merge2@1.4.1: + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, + } + engines: { node: '>= 8' } + + micromatch@4.0.8: + resolution: + { + integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, + } + engines: { node: '>=8.6' } + + mimic-fn@4.0.0: + resolution: + { + integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, + } + engines: { node: '>=12' } + + mimic-function@5.0.1: + resolution: + { + integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==, + } + engines: { node: '>=18' } + + minimatch@10.2.5: + resolution: + { + integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==, + } + engines: { node: 18 || 20 || >=22 } + + minimatch@3.1.5: + resolution: + { + integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==, + } + + minimatch@9.0.9: + resolution: + { + integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==, + } + engines: { node: '>=16 || 14 >=14.17' } + + minimist@1.2.8: + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, + } + + minipass@7.1.3: + resolution: + { + integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==, + } + engines: { node: '>=16 || 14 >=14.17' } + + mri@1.2.0: + resolution: + { + integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==, + } + engines: { node: '>=4' } + + ms@2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + + nanoid@3.3.15: + resolution: + { + integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + + natural-compare@1.4.0: + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, + } + + node-exports-info@1.6.2: + resolution: + { + integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==, + } + engines: { node: '>= 0.4' } + + node-html-parser@7.1.0: + resolution: + { + integrity: sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ==, + } + + node-releases@2.0.50: + resolution: + { + integrity: sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==, + } + engines: { node: '>=18' } + + npm-run-path@5.3.0: + resolution: + { + integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + nth-check@2.1.1: + resolution: + { + integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, + } + + object-inspect@1.13.4: + resolution: + { + integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, + } + engines: { node: '>= 0.4' } + + object-keys@1.1.1: + resolution: + { + integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, + } + engines: { node: '>= 0.4' } + + object.assign@4.1.7: + resolution: + { + integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==, + } + engines: { node: '>= 0.4' } + + object.entries@1.1.9: + resolution: + { + integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==, + } + engines: { node: '>= 0.4' } + + object.fromentries@2.0.8: + resolution: + { + integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==, + } + engines: { node: '>= 0.4' } + + object.groupby@1.0.3: + resolution: + { + integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==, + } + engines: { node: '>= 0.4' } + + object.values@1.2.1: + resolution: + { + integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==, + } + engines: { node: '>= 0.4' } + + onetime@6.0.0: + resolution: + { + integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, + } + engines: { node: '>=12' } + + onetime@7.0.0: + resolution: + { + integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==, + } + engines: { node: '>=18' } + + optionator@0.9.4: + resolution: + { + integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, + } + engines: { node: '>= 0.8.0' } + + outdent@0.5.0: + resolution: + { + integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==, + } + + own-keys@1.0.1: + resolution: + { + integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==, + } + engines: { node: '>= 0.4' } + + p-filter@2.1.0: + resolution: + { + integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==, + } + engines: { node: '>=8' } + + p-limit@2.3.0: + resolution: + { + integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, + } + engines: { node: '>=6' } + + p-limit@3.1.0: + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, + } + engines: { node: '>=10' } + + p-limit@4.0.0: + resolution: + { + integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + p-locate@4.1.0: + resolution: + { + integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, + } + engines: { node: '>=8' } + + p-locate@5.0.0: + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, + } + engines: { node: '>=10' } + + p-locate@6.0.0: + resolution: + { + integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + p-map@2.1.0: + resolution: + { + integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==, + } + engines: { node: '>=6' } + + p-try@2.2.0: + resolution: + { + integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, + } + engines: { node: '>=6' } + + package-json-from-dist@1.0.1: + resolution: + { + integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, + } + + package-manager-detector@0.2.11: + resolution: + { + integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==, + } + + parent-module@1.0.1: + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, + } + engines: { node: '>=6' } + + parse-json@5.2.0: + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, + } + engines: { node: '>=8' } + + parse5@8.0.1: + resolution: + { + integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==, + } + + path-exists@4.0.0: + resolution: + { + integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, + } + engines: { node: '>=8' } + + path-exists@5.0.0: + resolution: + { + integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + + path-key@3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: '>=8' } + + path-key@4.0.0: + resolution: + { + integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, + } + engines: { node: '>=12' } + + path-parse@1.0.7: + resolution: + { + integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, + } + + path-scurry@1.11.1: + resolution: + { + integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, + } + engines: { node: '>=16 || 14 >=14.18' } + + path-type@4.0.0: + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, + } + engines: { node: '>=8' } + + pathe@1.1.2: + resolution: + { + integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==, + } + + pathe@2.0.3: + resolution: + { + integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, + } + + pathval@2.0.1: + resolution: + { + integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, + } + engines: { node: '>= 14.16' } + + picocolors@1.1.1: + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } + + picomatch@2.3.2: + resolution: + { + integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==, + } + engines: { node: '>=8.6' } + + picomatch@4.0.4: + resolution: + { + integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==, + } + engines: { node: '>=12' } + + pidtree@0.6.1: + resolution: + { + integrity: sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==, + } + engines: { node: '>=0.10' } + hasBin: true + + pify@4.0.1: + resolution: + { + integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==, + } + engines: { node: '>=6' } + + possible-typed-array-names@1.1.0: + resolution: + { + integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==, + } + engines: { node: '>= 0.4' } + + postcss@8.5.15: + resolution: + { + integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==, + } + engines: { node: ^10 || ^12 || >=14 } + + prelude-ls@1.2.1: + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, + } + engines: { node: '>= 0.8.0' } + + prettier@2.8.8: + resolution: + { + integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==, + } + engines: { node: '>=10.13.0' } + hasBin: true + + prettier@3.8.4: + resolution: + { + integrity: sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==, + } + engines: { node: '>=14' } + hasBin: true + + prompts@2.4.2: + resolution: + { + integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==, + } + engines: { node: '>= 6' } + + punycode@2.3.1: + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, + } + engines: { node: '>=6' } + + quansync@0.2.11: + resolution: + { + integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==, + } + + queue-microtask@1.2.3: + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, + } + + react-dom@18.3.1: + resolution: + { + integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==, + } + peerDependencies: + react: ^18.3.1 + + react-refresh@0.17.0: + resolution: + { + integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==, + } + engines: { node: '>=0.10.0' } + + react@18.3.1: + resolution: + { + integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==, + } + engines: { node: '>=0.10.0' } + + read-yaml-file@1.1.0: + resolution: + { + integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==, + } + engines: { node: '>=6' } + + rechoir@0.8.0: + resolution: + { + integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==, + } + engines: { node: '>= 10.13.0' } + + reflect.getprototypeof@1.0.10: + resolution: + { + integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==, + } + engines: { node: '>= 0.4' } + + regexp-tree@0.1.27: + resolution: + { + integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==, + } + hasBin: true + + regexp.prototype.flags@1.5.4: + resolution: + { + integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==, + } + engines: { node: '>= 0.4' } + + require-directory@2.1.1: + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, + } + engines: { node: '>=0.10.0' } + + require-from-string@2.0.2: + resolution: + { + integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, + } + engines: { node: '>=0.10.0' } + + resolve-from@4.0.0: + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, + } + engines: { node: '>=4' } + + resolve-from@5.0.0: + resolution: + { + integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==, + } + engines: { node: '>=8' } + + resolve@1.22.12: + resolution: + { + integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==, + } + engines: { node: '>= 0.4' } + hasBin: true + + resolve@2.0.0-next.7: + resolution: + { + integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==, + } + engines: { node: '>= 0.4' } + hasBin: true + + restore-cursor@5.1.0: + resolution: + { + integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==, + } + engines: { node: '>=18' } + + reusify@1.1.0: + resolution: + { + integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, + } + engines: { iojs: '>=1.0.0', node: '>=0.10.0' } + + rfdc@1.4.1: + resolution: + { + integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==, + } + + rollup@2.80.0: + resolution: + { + integrity: sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==, + } + engines: { node: '>=10.0.0' } + hasBin: true + + rollup@4.62.2: + resolution: + { + integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==, + } + engines: { node: '>=18.0.0', npm: '>=8.0.0' } + hasBin: true + + run-parallel@1.2.0: + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, + } + + rxjs@7.5.7: + resolution: + { + integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==, + } + + safe-array-concat@1.1.4: + resolution: + { + integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==, + } + engines: { node: '>=0.4' } + + safe-push-apply@1.0.0: + resolution: + { + integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==, + } + engines: { node: '>= 0.4' } + + safe-regex-test@1.1.0: + resolution: + { + integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, + } + engines: { node: '>= 0.4' } + + safe-regex@2.1.1: + resolution: + { + integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==, + } + + safer-buffer@2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } + + saxes@6.0.0: + resolution: + { + integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==, + } + engines: { node: '>=v12.22.7' } + + scheduler@0.23.2: + resolution: + { + integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==, + } + + semver@6.3.1: + resolution: + { + integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, + } + hasBin: true + + semver@7.8.5: + resolution: + { + integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==, + } + engines: { node: '>=10' } + hasBin: true + + set-function-length@1.2.2: + resolution: + { + integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, + } + engines: { node: '>= 0.4' } + + set-function-name@2.0.2: + resolution: + { + integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==, + } + engines: { node: '>= 0.4' } + + set-proto@1.0.0: + resolution: + { + integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==, + } + engines: { node: '>= 0.4' } + + shebang-command@2.0.0: + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: '>=8' } + + shebang-regex@3.0.0: + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: '>=8' } + + side-channel-list@1.0.1: + resolution: + { + integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, + } + engines: { node: '>= 0.4' } + + side-channel-map@1.0.1: + resolution: + { + integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, + } + engines: { node: '>= 0.4' } + + side-channel-weakmap@1.0.2: + resolution: + { + integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, + } + engines: { node: '>= 0.4' } + + side-channel@1.1.1: + resolution: + { + integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==, + } + engines: { node: '>= 0.4' } + + siginfo@2.0.0: + resolution: + { + integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, + } + + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: '>=14' } + + sisteransi@1.0.5: + resolution: + { + integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, + } + + slash@3.0.0: + resolution: + { + integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, + } + engines: { node: '>=8' } + + slice-ansi@5.0.0: + resolution: + { + integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==, + } + engines: { node: '>=12' } + + slice-ansi@7.1.2: + resolution: + { + integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==, + } + engines: { node: '>=18' } + + source-map-js@1.2.1: + resolution: + { + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, + } + engines: { node: '>=0.10.0' } + + spawndamnit@3.0.1: + resolution: + { + integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==, + } + + split2@4.2.0: + resolution: + { + integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, + } + engines: { node: '>= 10.x' } + + sprintf-js@1.0.3: + resolution: + { + integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, + } + + stackback@0.0.2: + resolution: + { + integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, + } + + std-env@3.10.0: + resolution: + { + integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==, + } + + stop-iteration-iterator@1.1.0: + resolution: + { + integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==, + } + engines: { node: '>= 0.4' } + + string-argv@0.3.2: + resolution: + { + integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==, + } + engines: { node: '>=0.6.19' } + + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: '>=8' } + + string-width@5.1.2: + resolution: + { + integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, + } + engines: { node: '>=12' } + + string-width@7.2.0: + resolution: + { + integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==, + } + engines: { node: '>=18' } + + string.prototype.trim@1.2.11: + resolution: + { + integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==, + } + engines: { node: '>= 0.4' } + + string.prototype.trimend@1.0.10: + resolution: + { + integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==, + } + engines: { node: '>= 0.4' } + + string.prototype.trimstart@1.0.8: + resolution: + { + integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==, + } + engines: { node: '>= 0.4' } + + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: '>=8' } + + strip-ansi@7.2.0: + resolution: + { + integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==, + } + engines: { node: '>=12' } + + strip-bom@3.0.0: + resolution: + { + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, + } + engines: { node: '>=4' } + + strip-final-newline@3.0.0: + resolution: + { + integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, + } + engines: { node: '>=12' } + + strip-json-comments@3.1.1: + resolution: + { + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, + } + engines: { node: '>=8' } + + supports-color@7.2.0: + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: '>=8' } + + supports-preserve-symlinks-flag@1.0.0: + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, + } + engines: { node: '>= 0.4' } + + symbol-tree@3.2.4: + resolution: + { + integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==, + } + + tapable@2.3.3: + resolution: + { + integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==, + } + engines: { node: '>=6' } + + teamcity-service-messages@0.1.14: + resolution: + { + integrity: sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w==, + } + + term-size@2.2.1: + resolution: + { + integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==, + } + engines: { node: '>=8' } + + test-exclude@7.0.2: + resolution: + { + integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==, + } + engines: { node: '>=18' } + + text-extensions@2.4.0: + resolution: + { + integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==, + } + engines: { node: '>=8' } + + through@2.3.8: + resolution: + { + integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, + } + + tinybench@2.9.0: + resolution: + { + integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, + } + + tinyexec@0.3.2: + resolution: + { + integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==, + } + + tinyexec@1.2.4: + resolution: + { + integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==, + } + engines: { node: '>=18' } + + tinyglobby@0.2.17: + resolution: + { + integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==, + } + engines: { node: '>=12.0.0' } + + tinypool@1.1.1: + resolution: + { + integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + + tinyrainbow@1.2.0: + resolution: + { + integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==, + } + engines: { node: '>=14.0.0' } + + tinyspy@3.0.2: + resolution: + { + integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==, + } + engines: { node: '>=14.0.0' } + + tldts-core@7.4.4: + resolution: + { + integrity: sha512-vwVLJVvvpslm7vqAH7+XNj/neA/Ynq7DT2EEcMuwc5YzN5XaMyRAqxwU+uX3azZ1FQtB2gvrvnLnAEkvYlVdfg==, + } + + tldts@7.4.4: + resolution: + { + integrity: sha512-kFXFK7O4WPextIUAOk8qtnw9dxR9UIXP9CjuH1cTBVBZMDeQcUPgr/IazGiw1B0Yiw5L75gHLWeW4iD793r90g==, + } + hasBin: true + + to-regex-range@5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: '>=8.0' } + + tough-cookie@6.0.1: + resolution: + { + integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==, + } + engines: { node: '>=16' } + + tr46@6.0.0: + resolution: + { + integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==, + } + engines: { node: '>=20' } + + ts-api-utils@1.4.3: + resolution: + { + integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==, + } + engines: { node: '>=16' } + peerDependencies: + typescript: '>=4.2.0' + + tsconfig-paths-webpack-plugin@4.2.0: + resolution: + { + integrity: sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==, + } + engines: { node: '>=10.13.0' } + + tsconfig-paths@3.15.0: + resolution: + { + integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==, + } + + tsconfig-paths@4.2.0: + resolution: + { + integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, + } + engines: { node: '>=6' } + + tslib@2.8.1: + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } + + turbo@2.10.0: + resolution: + { + integrity: sha512-o016H9PPtuH2deb3mh3Vci3Avfi9UYgM/RONQisY7HnloupP0IFSbFS3gFYJgFJP8nwBrByHWFQIDa8T2zIXPw==, + } + hasBin: true + + type-check@0.4.0: + resolution: + { + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, + } + engines: { node: '>= 0.8.0' } + + typed-array-buffer@1.0.3: + resolution: + { + integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==, + } + engines: { node: '>= 0.4' } + + typed-array-byte-length@1.0.3: + resolution: + { + integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==, + } + engines: { node: '>= 0.4' } + + typed-array-byte-offset@1.0.4: + resolution: + { + integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==, + } + engines: { node: '>= 0.4' } + + typed-array-length@1.0.8: + resolution: + { + integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==, + } + engines: { node: '>= 0.4' } + + typescript-eslint@7.18.0: + resolution: + { + integrity: sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==, + } + engines: { node: ^18.18.0 || >=20.0.0 } + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + typescript@5.9.3: + resolution: + { + integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, + } + engines: { node: '>=14.17' } + hasBin: true + + unbox-primitive@1.1.0: + resolution: + { + integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==, + } + engines: { node: '>= 0.4' } + + undici-types@8.3.0: + resolution: + { + integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==, + } + + undici@7.28.0: + resolution: + { + integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==, + } + engines: { node: '>=20.18.1' } + + unicorn-magic@0.1.0: + resolution: + { + integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==, + } + engines: { node: '>=18' } + + universalify@0.1.2: + resolution: + { + integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==, + } + engines: { node: '>= 4.0.0' } + + universalify@2.0.1: + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, + } + engines: { node: '>= 10.0.0' } + + update-browserslist-db@1.2.3: + resolution: + { + integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, + } + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, + } + + vite-node@2.1.9: + resolution: + { + integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + + vite@5.4.21: + resolution: + { + integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@2.1.9: + resolution: + { + integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==, + } + engines: { node: ^18.0.0 || >=20.0.0 } + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.9 + '@vitest/ui': 2.1.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: + { + integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==, + } + engines: { node: '>=18' } + + watskeburt@4.2.3: + resolution: + { + integrity: sha512-uG9qtQYoHqAsnT711nG5iZc/8M5inSmkGCOp7pFaytKG2aTfIca7p//CjiVzAE4P7hzaYuCozMjNNaLgmhbK5g==, + } + engines: { node: ^18||>=20 } + hasBin: true + + webidl-conversions@8.0.1: + resolution: + { + integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==, + } + engines: { node: '>=20' } + + whatwg-mimetype@5.0.0: + resolution: + { + integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==, + } + engines: { node: '>=20' } + + whatwg-url@16.0.1: + resolution: + { + integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==, + } + engines: { node: ^20.19.0 || ^22.12.0 || >=24.0.0 } + + which-boxed-primitive@1.1.1: + resolution: + { + integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==, + } + engines: { node: '>= 0.4' } + + which-builtin-type@1.2.1: + resolution: + { + integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==, + } + engines: { node: '>= 0.4' } + + which-collection@1.0.2: + resolution: + { + integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==, + } + engines: { node: '>= 0.4' } + + which-typed-array@1.1.22: + resolution: + { + integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==, + } + engines: { node: '>= 0.4' } + + which@2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: '>= 8' } + hasBin: true + + why-is-node-running@2.3.0: + resolution: + { + integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, + } + engines: { node: '>=8' } + hasBin: true + + word-wrap@1.2.5: + resolution: + { + integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, + } + engines: { node: '>=0.10.0' } + + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: '>=10' } + + wrap-ansi@8.1.0: + resolution: + { + integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, + } + engines: { node: '>=12' } + + wrap-ansi@9.0.2: + resolution: + { + integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==, + } + engines: { node: '>=18' } + + xml-name-validator@5.0.0: + resolution: + { + integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==, + } + engines: { node: '>=18' } + + xmlchars@2.2.0: + resolution: + { + integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==, + } + + y18n@5.0.8: + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, + } + engines: { node: '>=10' } + + yallist@3.1.1: + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, + } + + yaml@2.9.0: + resolution: + { + integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==, + } + engines: { node: '>= 14.6' } + hasBin: true + + yargs-parser@21.1.1: + resolution: + { + integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, + } + engines: { node: '>=12' } + + yargs@17.7.3: + resolution: + { + integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==, + } + engines: { node: '>=12' } + + yocto-queue@0.1.0: + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, + } + engines: { node: '>=10' } + + yocto-queue@1.2.2: + resolution: + { + integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==, + } + engines: { node: '>=12.20' } + +snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@asamuzakjp/dom-selector@7.1.1': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.7': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/runtime@7.29.7': {} + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/traverse@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@bcoe/v8-coverage@0.2.3': {} + + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + + '@changesets/apply-release-plan@7.1.1': + dependencies: + '@changesets/config': 3.1.4 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.8.5 + + '@changesets/assemble-release-plan@6.0.10': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.8.5 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.31.0(@types/node@26.0.1)': + dependencies: + '@changesets/apply-release-plan': 7.1.1 + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.4 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/get-release-plan': 4.0.16 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@inquirer/external-editor': 1.0.3(@types/node@26.0.1) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.8.5 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.4': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/logger': 0.1.1 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.4': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.8.5 + + '@changesets/get-release-plan@4.0.16': + dependencies: + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/config': 3.1.4 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.3': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.2.0 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.7': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.3 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.2.0 + prettier: 2.8.8 + + '@commitlint/cli@19.8.1(@types/node@26.0.1)(typescript@5.9.3)': + dependencies: + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@26.0.1)(typescript@5.9.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 + tinyexec: 1.2.4 + yargs: 17.7.3 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + ajv: 8.20.0 + + '@commitlint/ensure@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@19.8.1': {} + + '@commitlint/format@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + + '@commitlint/is-ignored@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + semver: 7.8.5 + + '@commitlint/lint@19.8.1': + dependencies: + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/load@19.8.1(@types/node@26.0.1)(typescript@5.9.3)': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + cosmiconfig: 9.0.2(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@26.0.1)(cosmiconfig@9.0.2(typescript@5.9.3))(typescript@5.9.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@19.8.1': {} + + '@commitlint/parse@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.8.1': + dependencies: + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.2.4 + + '@commitlint/resolve-extends@19.8.1': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@19.8.1': + dependencies: + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/to-lines@19.8.1': {} + + '@commitlint/top-level@19.8.1': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.8.1': + dependencies: + '@types/conventional-commits-parser': 5.0.2 + chalk: 5.6.2 + + '@crxjs/vite-plugin@2.7.0(vite@5.4.21(@types/node@26.0.1))': + dependencies: + '@webcomponents/custom-elements': 1.6.0 + acorn-walk: 8.3.5 + convert-source-map: 1.9.0 + debug: 4.4.3 + es-module-lexer: 0.10.5 + fs-extra: 10.1.0 + jsesc: 3.1.0 + magic-string: 0.30.21 + node-html-parser: 7.1.0 + pathe: 2.0.3 + picocolors: 1.1.1 + rollup: 2.80.0 + rxjs: 7.5.7 + tinyglobby: 0.2.17 + vite: 5.4.21(@types/node@26.0.1) + transitivePeerDependencies: + - supports-color + + '@csstools/color-helpers@6.1.0': {} + + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.2.0 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@exodus/bytes@1.15.1': {} + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@inquirer/external-editor@1.0.3(@types/node@26.0.1)': + dependencies: + chardet: 2.2.0 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 26.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/schema@0.1.6': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.29.7 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.29.7 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + + '@rtsao/scc@1.1.0': {} + + '@turbo/darwin-64@2.10.0': + optional: true + + '@turbo/darwin-arm64@2.10.0': + optional: true + + '@turbo/linux-64@2.10.0': + optional: true + + '@turbo/linux-arm64@2.10.0': + optional: true + + '@turbo/windows-64@2.10.0': + optional: true + + '@turbo/windows-arm64@2.10.0': + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.7 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.7 + + '@types/chrome@0.0.268': + dependencies: + '@types/filesystem': 0.0.36 + '@types/har-format': 1.2.16 + + '@types/conventional-commits-parser@5.0.2': + dependencies: + '@types/node': 26.0.1 + + '@types/estree@1.0.9': {} + + '@types/filesystem@0.0.36': + dependencies: + '@types/filewriter': 0.0.33 + + '@types/filewriter@0.0.33': {} + + '@types/har-format@1.2.16': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/node@12.20.55': {} + + '@types/node@26.0.1': + dependencies: + undici-types: 8.3.0 + + '@types/prop-types@15.7.15': {} + + '@types/react-dom@18.3.7(@types/react@18.3.31)': + dependencies: + '@types/react': 18.3.31 + + '@types/react@18.3.31': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.2.3 + + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 9.39.4(jiti@2.6.1) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + + '@typescript-eslint/type-utils@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.4(jiti@2.6.1) + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.9 + semver: 7.8.5 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@26.0.1))': + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 5.4.21(@types/node@26.0.1) + transitivePeerDependencies: + - supports-color + + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@26.0.1)(jsdom@29.1.1))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 1.2.0 + vitest: 2.1.9(@types/node@26.0.1)(jsdom@29.1.1) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@2.1.9': + dependencies: + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@26.0.1))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@26.0.1) + + '@vitest/pretty-format@2.1.9': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.9': + dependencies: + '@vitest/utils': 2.1.9 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + magic-string: 0.30.21 + pathe: 1.1.2 + + '@vitest/spy@2.1.9': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + loupe: 3.2.1 + tinyrainbow: 1.2.0 + + '@webcomponents/custom-elements@1.6.0': {} + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + acorn-jsx-walk@2.0.0: {} + + acorn-jsx@5.3.2(acorn@8.17.0): + dependencies: + acorn: 8.17.0 + + acorn-loose@8.5.2: + dependencies: + acorn: 8.17.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-ify@1.0.0: {} + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array-union@2.1.0: {} + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + assertion-error@2.0.1: {} + + async-function@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.10.40: {} + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + boolbase@1.0.0: {} + + brace-expansion@1.1.15: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.1: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.4: + dependencies: + baseline-browser-mapping: 2.10.40 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.379 + node-releases: 2.0.50 + update-browserslist-db: 1.2.3(browserslist@4.28.4) + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001799: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + chardet@2.2.0: {} + + check-error@2.1.3: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + commander@13.1.0: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + concat-map@0.0.1: {} + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + cosmiconfig-typescript-loader@6.3.0(@types/node@26.0.1)(cosmiconfig@9.0.2(typescript@5.9.3))(typescript@5.9.3): + dependencies: + '@types/node': 26.0.1 + cosmiconfig: 9.0.2(typescript@5.9.3) + jiti: 2.6.1 + typescript: 5.9.3 + + cosmiconfig@9.0.2(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.2.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + csstype@3.2.3: {} + + dargs@8.1.0: {} + + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + dependency-cruiser@16.10.4: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + acorn-jsx-walk: 2.0.0 + acorn-loose: 8.5.2 + acorn-walk: 8.3.5 + ajv: 8.20.0 + commander: 13.1.0 + enhanced-resolve: 5.24.1 + ignore: 7.0.5 + interpret: 3.1.1 + is-installed-globally: 1.0.0 + json5: 2.2.3 + memoize: 10.2.0 + picocolors: 1.1.1 + picomatch: 4.0.4 + prompts: 2.4.2 + rechoir: 0.8.0 + safe-regex: 2.1.1 + semver: 7.8.5 + teamcity-service-messages: 0.1.14 + tsconfig-paths-webpack-plugin: 4.2.0 + watskeburt: 4.2.3 + + detect-indent@6.1.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.379: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enhanced-resolve@5.24.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@4.5.0: {} + + entities@8.0.0: {} + + env-paths@2.2.1: {} + + environment@1.1.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-abstract-get@1.0.0: + dependencies: + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + is-callable: 1.2.7 + object-inspect: 1.13.4 + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.4 + function.prototype.name: 1.2.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.8 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.22 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@0.10.5: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.4 + + es-to-primitive@1.3.4: + dependencies: + es-abstract-get: 1.0.0 + es-define-property: 1.0.1 + es-errors: 1.3.0 + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-import-resolver-node@0.3.10: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.2 + resolve: 2.0.0-next.7 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.13.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) + eslint-import-resolver-node: 0.3.10 + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.39.4(jiti@2.6.1) + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.13.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.4(jiti@2.6.1)) + hasown: 2.0.4 + is-core-module: 2.16.2 + is-glob: 4.0.3 + minimatch: 3.1.5 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.10 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.4(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + eventemitter3@5.0.4: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + expect-type@1.4.0: {} + + extendable-error@0.1.7: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.1.2: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flatted@3.4.2: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.2.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + es-define-property: 1.0.1 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 + is-callable: 1.2.7 + is-document.all: 1.0.0 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.6.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-stream@8.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + globals@14.0.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + + html-escaper@2.0.2: {} + + human-id@4.2.0: {} + + human-signals@5.0.0: {} + + husky@9.1.7: {} + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + imurmurhash@0.1.4: {} + + ini@4.1.1: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.1 + + interpret@3.1.1: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.6.0 + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-installed-globally@1.0.0: + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-path-inside@4.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@3.0.0: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-windows@1.0.2: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@2.6.1: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.2.0: + dependencies: + argparse: 2.0.1 + + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.1 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + undici: 7.28.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@3.0.3: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.5.2: + dependencies: + chalk: 5.6.2 + commander: 13.1.0 + debug: 4.4.3 + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.3.3 + micromatch: 4.0.8 + pidtree: 0.6.1 + string-argv: 0.3.2 + yaml: 2.9.0 + transitivePeerDependencies: + - supports-color + + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.camelcase@4.3.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.2.1: {} + + lru-cache@10.4.3: {} + + lru-cache@11.5.1: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + + math-intrinsics@1.1.0: {} + + mdn-data@2.27.1: {} + + memoize@10.2.0: + dependencies: + mimic-function: 5.0.1 + + meow@12.1.1: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.6 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.15 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.1 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mri@1.2.0: {} + + ms@2.1.3: {} + + nanoid@3.3.15: {} + + natural-compare@1.4.0: {} + + node-exports-info@1.6.2: + dependencies: + array.prototype.flatmap: 1.3.3 + es-errors: 1.3.0 + object.entries: 1.1.9 + semver: 6.3.1 + + node-html-parser@7.1.0: + dependencies: + css-select: 5.2.2 + he: 1.2.0 + + node-releases@2.0.50: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + outdent@0.5.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-map@2.1.0: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.7 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse5@8.0.1: + dependencies: + entities: 8.0.0 + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-type@4.0.0: {} + + pathe@1.1.2: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pidtree@0.6.1: {} + + pify@4.0.1: {} + + possible-typed-array-names@1.1.0: {} + + postcss@8.5.15: + dependencies: + nanoid: 3.3.15 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@2.8.8: {} + + prettier@3.8.4: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + punycode@2.3.1: {} + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-refresh@0.17.0: {} + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + rechoir@0.8.0: + dependencies: + resolve: 1.22.12 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.7: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + node-exports-info: 1.6.2 + object-keys: 1.1.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup@2.80.0: + optionalDependencies: + fsevents: 2.3.3 + + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.5.7: + dependencies: + tslib: 2.8.1 + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex@2.1.1: + dependencies: + regexp-tree: 0.1.27 + + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + semver@6.3.1: {} + + semver@7.8.5: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + source-map-js@1.2.1: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + + string.prototype.trim@1.2.11: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 + + string.prototype.trimend@1.0.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@3.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + tapable@2.3.3: {} + + teamcity-service-messages@0.1.14: {} + + term-size@2.2.1: {} + + test-exclude@7.0.2: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 10.5.0 + minimatch: 10.2.5 + + text-extensions@2.4.0: {} + + through@2.3.8: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinypool@1.1.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + tldts-core@7.4.4: {} + + tldts@7.4.4: + dependencies: + tldts-core: 7.4.4 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tough-cookie@6.0.1: + dependencies: + tldts: 7.4.4 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + + ts-api-utils@1.4.3(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + tsconfig-paths-webpack-plugin@4.2.0: + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.24.1 + tapable: 2.3.3 + tsconfig-paths: 4.2.0 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + turbo@2.10.0: + optionalDependencies: + '@turbo/darwin-64': 2.10.0 + '@turbo/darwin-arm64': 2.10.0 + '@turbo/linux-64': 2.10.0 + '@turbo/linux-arm64': 2.10.0 + '@turbo/windows-64': 2.10.0 + '@turbo/windows-arm64': 2.10.0 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript-eslint@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.6.1) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + typescript@5.9.3: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@8.3.0: {} + + undici@7.28.0: {} + + unicorn-magic@0.1.0: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.2.3(browserslist@4.28.4): + dependencies: + browserslist: 4.28.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + vite-node@2.1.9(@types/node@26.0.1): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@26.0.1) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.21(@types/node@26.0.1): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.15 + rollup: 4.62.2 + optionalDependencies: + '@types/node': 26.0.1 + fsevents: 2.3.3 + + vitest@2.1.9(@types/node@26.0.1)(jsdom@29.1.1): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@26.0.1)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.4.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@26.0.1) + vite-node: 2.1.9(@types/node@26.0.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 26.0.1 + jsdom: 29.1.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + watskeburt@4.2.3: {} + + webidl-conversions@8.0.1: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.2.0 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.22 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@2.9.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yocto-queue@1.2.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..8dda810 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,4 @@ +packages: + - 'apps/*' + - 'packages/*' + - 'connectors/*' diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..025476d --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "declaration": true, + "declarationMap": true, + "exactOptionalPropertyTypes": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cc8664f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "files": [], + "references": [ + { "path": "./packages/types" }, + { "path": "./packages/shared" }, + { "path": "./packages/utils" }, + { "path": "./packages/extractor" }, + { "path": "./packages/storage" }, + { "path": "./packages/exporters" }, + { "path": "./packages/ocr" }, + { "path": "./packages/ai" }, + { "path": "./connectors/instagram" }, + { "path": "./apps/extension" } + ] +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..cbcc15f --- /dev/null +++ b/turbo.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://turbo.build/schema.json", + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", "lib/**"] + }, + "test": { + "dependsOn": ["build"] + }, + "lint": { + "dependsOn": ["^lint"] + }, + "typecheck": { + "dependsOn": ["^typecheck"] + }, + "dev": { + "cache": false, + "persistent": true + } + } +} From 20dcd302965bbebfba1d7e1de6214015c3426741 Mon Sep 17 00:00:00 2001 From: cynox-66 Date: Fri, 26 Jun 2026 18:42:23 +0530 Subject: [PATCH 2/7] feat(alpha): add diagnostic infrastructure, failure capture, and alpha-report template --- apps/extension/src/background/index.ts | 95 ++++- apps/extension/src/content/index.ts | 131 ++++++- apps/extension/src/popup/index.tsx | 365 +++++++++++++++--- docs/verification/alpha-report.md | 177 +++++++++ packages/shared/src/diagnostics-collector.ts | 80 ++++ packages/shared/src/index.ts | 1 + packages/types/src/diagnostics/diagnostics.ts | 42 ++ packages/types/src/diagnostics/index.ts | 1 + packages/types/src/index.ts | 1 + 9 files changed, 808 insertions(+), 85 deletions(-) create mode 100644 docs/verification/alpha-report.md create mode 100644 packages/shared/src/diagnostics-collector.ts create mode 100644 packages/types/src/diagnostics/diagnostics.ts create mode 100644 packages/types/src/diagnostics/index.ts diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index aa6b610..5d45327 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -1,13 +1,17 @@ /** - * Background Worker — Pipeline Orchestrator + * Background Worker — Pipeline Orchestrator (Alpha Diagnostic Build) * - * Receives discovery batches from the Content Script, runs normalization - * through the InstagramConnector, persists to InMemoryStorage, and emits - * domain events to the Popup UI. - * - * This worker is completely ignorant of the Instagram DOM. + * Extended with DiagnosticsCollector integration. + * Every failure is recorded with category, root cause, and DOM snapshot. + * Sessions export as structured JSON for alpha-report.md population. */ -import { Logger, featureFlags, FeatureFlag, MetricsCollector } from '@knowledge-extractor/shared'; +import { + Logger, + featureFlags, + FeatureFlag, + MetricsCollector, + DiagnosticsCollector, +} from '@knowledge-extractor/shared'; import { InMemoryStorage } from '@knowledge-extractor/storage'; import { InstagramConnector } from '@knowledge-extractor/connector-instagram'; import { IDiscoveredResource } from '@knowledge-extractor/types'; @@ -16,6 +20,7 @@ const logger = new Logger('BackgroundWorker'); const storage = new InMemoryStorage(); const connector = new InstagramConnector(); const metrics = new MetricsCollector(); +const diagnostics = new DiagnosticsCollector(); // ---- Helpers ---------------------------------------------------------------- function emitEvent(stage: string, data: unknown): void { @@ -25,32 +30,50 @@ function emitEvent(stage: string, data: unknown): void { } // ---- Message Dispatcher ----------------------------------------------------- -chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { +chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if (message.action === 'START_PIPELINE') { - handleStartPipeline().then(sendResponse); + handleStartPipeline() + .then(sendResponse) + .catch(() => sendResponse({ success: false })); return true; } if (message.action === 'RESOURCES_DISCOVERED') { - handleDiscoveryBatch(message.data).catch((err) => logger.error('Discovery batch error', err)); + handleDiscoveryBatch( + message.data as Array<{ resource: IDiscoveredResource; fingerprint: string }>, + ).catch((err: unknown) => logger.error('Discovery batch error', err)); return false; } + + if (message.action === 'EXPORT_DIAGNOSTICS') { + handleExportDiagnostics() + .then(sendResponse) + .catch(() => sendResponse(null)); + return true; + } }); // ---- Pipeline stages -------------------------------------------------------- async function handleStartPipeline(): Promise<{ success: boolean }> { metrics.reset(); + const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { logger.error('No active tab'); return { success: false }; } + const pageUrl = tabs[0].url ?? 'unknown'; + diagnostics.reset(pageUrl); + try { await chrome.tabs.sendMessage(tabs[0].id, { action: 'RUN_PIPELINE' }); - emitEvent('PIPELINE_STARTED', { tabId: tabs[0].id }); + emitEvent('PIPELINE_STARTED', { tabId: tabs[0].id, pageUrl }); return { success: true }; } catch (err) { + diagnostics.recordFailure(pageUrl, 'unknown', 'Failed to inject content script', { + errorDetail: String(err), + }); logger.error('Failed to reach content script', err); return { success: false }; } @@ -71,22 +94,28 @@ async function handleDiscoveryBatch( const extractStart = Date.now(); try { - // We delegate to the connector which owns the article in its own DOM - // context. For the background worker we inject a tab script to get - // the article element and pass the parsed representation back. - // For Sprint 3 we ask the content script to extract a specific URI. const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) continue; - const rawResult = await chrome.tabs.sendMessage(tabs[0].id, { + const rawResult = (await chrome.tabs.sendMessage(tabs[0].id, { action: 'EXTRACT_RESOURCE', data: { targetUri: resource.targetUri }, - }); + })) as { success: boolean; data?: unknown; domSnapshot?: string; error?: string } | undefined; metrics.addExtractionTime(Date.now() - extractStart); if (!rawResult?.success) { metrics.recordFailed(); + diagnostics.recordFailure( + resource.targetUri, + classifyExtractionError(rawResult?.error), + rawResult?.error ?? 'Content script returned failure', + { domSnapshot: rawResult?.domSnapshot }, + ); + emitEvent('EXTRACTION_FAILED', { + uri: resource.targetUri, + reason: rawResult?.error, + }); continue; } @@ -96,7 +125,9 @@ async function handleDiscoveryBatch( } const normStart = Date.now(); - const normalized = await connector.normalize(rawResult.data); + const normalized = await connector.normalize( + rawResult.data as Parameters[0], + ); metrics.addNormalizationTime(Date.now() - normStart); metrics.recordExtracted(); @@ -109,10 +140,36 @@ async function handleDiscoveryBatch( emitEvent('RESOURCE_STORED', { id: normalized.id }); } } catch (err) { + const errorStr = String(err); logger.error(`Failed to process resource: ${resource.targetUri}`, err); metrics.recordFailed(); + diagnostics.recordFailure(resource.targetUri, classifyExtractionError(errorStr), errorStr, { + errorDetail: errorStr, + }); } } - emitEvent('METRICS_SNAPSHOT', metrics.snapshot()); + const snapshot = metrics.snapshot(); + const report = diagnostics.buildReport(snapshot); + emitEvent('METRICS_SNAPSHOT', snapshot); + emitEvent('DIAGNOSTICS_SNAPSHOT', report); +} + +async function handleExportDiagnostics(): Promise { + const snapshot = metrics.snapshot(); + return diagnostics.buildReport(snapshot); +} + +function classifyExtractionError( + error?: string, +): import('@knowledge-extractor/types').FailureCategory { + if (!error) return 'unknown'; + const e = error.toLowerCase(); + if (e.includes('selector') || e.includes('queryselector') || e.includes('no article')) + return 'selector_failure'; + if (e.includes('parse') || e.includes('json') || e.includes('syntax')) return 'parsing_failure'; + if (e.includes('normaliz') || e.includes('resource') || e.includes('contract')) + return 'normalization_failure'; + if (e.includes('network') || e.includes('fetch') || e.includes('cors')) return 'network_error'; + return 'unknown'; } diff --git a/apps/extension/src/content/index.ts b/apps/extension/src/content/index.ts index b7919c4..f7756c1 100644 --- a/apps/extension/src/content/index.ts +++ b/apps/extension/src/content/index.ts @@ -1,12 +1,8 @@ /** - * Content Script — DOM Adapter Layer + * Content Script — DOM Adapter Layer (Alpha Diagnostic Build) * - * Responsibility: Observe the Instagram DOM and relay raw article elements - * as structured payloads to the Background Worker. - * - * This script is deliberately free of domain model logic. It knows about - * browser APIs and the Instagram page structure only through the - * DiscoveryEngine and the strategy chain that lives in the connector package. + * Extended with DOM snapshot capture for failure analysis. + * Snapshots are trimmed to 2000 chars and only captured on failure. */ import { IDiscoveredResource } from '@knowledge-extractor/types'; import { Logger, featureFlags, FeatureFlag, MetricsCollector } from '@knowledge-extractor/shared'; @@ -16,7 +12,6 @@ const logger = new Logger('ContentScript'); const metrics = new MetricsCollector(); const engine = new DiscoveryEngine(); -// Discovery queue: discovered resources waiting to be batch-sent const pendingQueue: Array<{ resource: IDiscoveredResource; fingerprint: string }> = []; let flushTimer: ReturnType | null = null; @@ -25,7 +20,7 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if (message.action === 'RUN_PIPELINE') { startDiscovery() .then(() => sendResponse({ success: true })) - .catch((err) => { + .catch((err: unknown) => { logger.error('Pipeline error', err); sendResponse({ success: false, error: String(err) }); }); @@ -37,6 +32,14 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { sendResponse({ metrics: metrics.snapshot() }); return true; } + + if (message.action === 'EXTRACT_RESOURCE') { + const { targetUri } = (message.data ?? {}) as { targetUri: string }; + extractSingleResource(targetUri) + .then(sendResponse) + .catch((err: unknown) => sendResponse({ success: false, error: String(err) })); + return true; + } }); // ---- Discovery orchestration ------------------------------------------------ @@ -61,21 +64,111 @@ function scheduleFlush(): void { flushTimer = setTimeout(() => { flushQueue(); flushTimer = null; - }, 150); // Debounce: batch DOM mutations within 150 ms + }, 150); } function flushQueue(): void { if (pendingQueue.length === 0) return; - const batch = pendingQueue.splice(0, pendingQueue.length); logger.debug(`Flushing ${batch.length} discovered resources to background`); + chrome.runtime.sendMessage({ action: 'RESOURCES_DISCOVERED', data: batch }).catch(() => {}); +} + +// ---- Per-resource extraction with DOM snapshot capture --------------------- +async function extractSingleResource(targetUri: string): Promise<{ + success: boolean; + data?: unknown; + domSnapshot?: string; + error?: string; +}> { + // Find the article element in the current DOM matching this URI + const articles = Array.from(document.querySelectorAll('article')); + const article = articles.find((a) => { + const link = + a.querySelector('a[href*="/p/"]') ?? + a.querySelector('a[href*="/reel/"]'); + return link?.href === targetUri || link?.href.includes(new URL(targetUri).pathname); + }); + + if (!article) { + // Single-page post view — use the whole document body + const bodyArticle = document.querySelector('article'); + if (!bodyArticle) { + return { + success: false, + domSnapshot: document.body.innerHTML.slice(0, 2000), + error: 'No article element found for URI', + }; + } + } + + const target = article ?? document.querySelector('article'); + if (!target) { + return { success: false, error: 'No article element available' }; + } - chrome.runtime - .sendMessage({ - action: 'RESOURCES_DISCOVERED', - data: batch, - }) - .catch(() => { - // Background may not be listening yet; silently discard - }); + // Capture a trimmed DOM snapshot for failure analysis + const domSnapshot = target.outerHTML.slice(0, 2000); + + try { + // Extract raw structured data from the DOM element + const link = + target.querySelector('a[href*="/p/"]') ?? + target.querySelector('a[href*="/reel/"]'); + + const sourceUri = link?.href ?? targetUri; + const match = sourceUri.match(/\/(?:p|reel)\/([A-Za-z0-9_-]+)/); + const externalId = match ? match[1] : ''; + + const authorEl = target.querySelector('header a[role="link"]'); + const authorHandle = authorEl?.textContent?.trim(); + const authorDisplayName = authorEl + ?.closest('header') + ?.querySelector('span:last-child') + ?.textContent?.trim(); + + const captionEl = target.querySelector( + '[data-testid="post-comment-root"] span, h1', + ); + const textContent = captionEl?.textContent?.trim(); + + const timeEl = target.querySelector('time[datetime]'); + const publishedAt = timeEl?.getAttribute('datetime') ?? undefined; + + const videoEl = target.querySelector('video'); + const videoUri = videoEl?.src || videoEl?.querySelector('source')?.src; + + const imgEls = Array.from( + target.querySelectorAll('img[srcset], img[src]'), + ).filter((img) => !img.src.includes('avatar') && (img.width > 100 || img.naturalWidth > 100)); + + const mediaUris = [...new Set(imgEls.map((img) => img.src).filter(Boolean))]; + + const isReel = sourceUri.includes('/reel/'); + const hasDots = target.querySelectorAll('[aria-label*="slide"], [class*="dot"]').length > 1; + const layout = + isReel || videoUri ? 'reel' : hasDots || mediaUris.length > 1 ? 'carousel' : 'single-image'; + + return { + success: true, + data: { + providerName: 'instagram', + sourceUri, + externalId, + authorHandle, + authorDisplayName, + textContent, + publishedAt, + mediaUris: videoUri ? [videoUri, ...mediaUris] : mediaUris, + videoUri, + layout, + }, + }; + } catch (err) { + return { + success: false, + domSnapshot, + error: String(err), + }; + } } diff --git a/apps/extension/src/popup/index.tsx b/apps/extension/src/popup/index.tsx index 4212947..47b9688 100644 --- a/apps/extension/src/popup/index.tsx +++ b/apps/extension/src/popup/index.tsx @@ -1,75 +1,346 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { createRoot } from 'react-dom/client'; +import type { ISessionReport, IFailureRecord } from '@knowledge-extractor/types'; +// ---- Types ------------------------------------------------------------------ +interface PipelineEvent { + stage: string; + payload: unknown; + ts: string; +} + +// ---- Helpers ---------------------------------------------------------------- +function downloadJson(data: unknown, filename: string): void { + const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + a.click(); + URL.revokeObjectURL(url); +} + +// ---- Sub-components --------------------------------------------------------- +const MetricsBadge = ({ label, value, warn }: { label: string; value: number; warn?: boolean }) => ( +
0 ? '#fff0f0' : '#f0f4ff', + borderRadius: 6, + minWidth: 60, + }} + > +
0 ? '#c00' : '#1a56db' }}> + {value} +
+
{label}
+
+); + +const FailureCard = ({ failure }: { failure: IFailureRecord }) => ( +
+ + [{failure.category}] {failure.targetUri.replace('https://www.instagram.com', '')} + +
+
+ Root cause: {failure.rootCause} +
+ {failure.failingStrategy && ( +
+ Strategy: {failure.failingStrategy} +
+ )} + {failure.domSnapshot && ( +
+ DOM Snapshot +
+            {failure.domSnapshot}
+          
+
+ )} +
+
+); + +// ---- Main Popup ------------------------------------------------------------- const Popup = () => { - const [status, setStatus] = useState('Idle'); - const [debugData, setDebugData] = useState([]); + const [status, setStatus] = useState<'idle' | 'running' | 'done' | 'error'>('idle'); + const [events, setEvents] = useState([]); + const [report, setReport] = useState(null); + const [activeTab, setActiveTab] = useState<'metrics' | 'failures' | 'log'>('metrics'); useEffect(() => { - const listener = (message: any) => { - if (message.action === 'SYSTEM_STATUS') { - setStatus(`Stage completed: ${message.data.stage}`); - setDebugData((prev) => [...prev, message.data]); + const listener = (message: { action: string; data: { stage: string; payload: unknown } }) => { + if (message.action !== 'SYSTEM_STATUS') return; + const { stage, payload } = message.data; + + setEvents((prev) => [...prev, { stage, payload, ts: new Date().toLocaleTimeString() }]); + + if (stage === 'DIAGNOSTICS_SNAPSHOT') { + setReport(payload as ISessionReport); } }; chrome.runtime.onMessage.addListener(listener); return () => chrome.runtime.onMessage.removeListener(listener); }, []); - const handleStart = () => { - setStatus('Pipeline starting...'); - setDebugData([]); - chrome.runtime.sendMessage({ action: 'START_PIPELINE' }, (response) => { - if (response?.success) { - setStatus('Pipeline completed successfully.'); - } else { - setStatus('Pipeline failed. Make sure you are on Instagram.'); - } - }); - }; + const handleStart = useCallback(() => { + setStatus('running'); + setEvents([]); + setReport(null); + chrome.runtime.sendMessage( + { action: 'START_PIPELINE' }, + (response: { success: boolean } | undefined) => { + setStatus(response?.success ? 'done' : 'error'); + }, + ); + }, []); + + const handleExport = useCallback(() => { + if (!report) return; + const ts = new Date().toISOString().slice(0, 19).replace(/:/g, '-'); + downloadJson(report, `alpha-session-${ts}.json`); + }, [report]); + + const statusColor = { idle: '#6b7280', running: '#d97706', done: '#16a34a', error: '#dc2626' }[ + status + ]; + const m = report?.metrics; return ( -
-

Knowledge Extractor

- -
- Status: {status} +
Knowledge Extractor
+
Alpha Diagnostics Build
+ {/* Controls */}
-

Debug Log

- {debugData.map((data, idx) => ( -
+ {status === 'running' ? 'Running…' : 'Start Extraction'} + + +
+ ● {status.toUpperCase()} +
+
+ + {/* Metrics strip */} + {m && ( +
+ + + + + + + + {report?.memoryUsageMb != null && ( + + )} +
+ )} + + {/* Tabs */} +
+ {(['metrics', 'failures', 'log'] as const).map((tab) => ( +
+ {tab} + {tab === 'failures' && report && report.failures.length > 0 + ? ` (${report.failures.length})` + : ''} + ))}
+ + {/* Tab content */} +
+ {activeTab === 'metrics' && report && ( +
+
+ Session: {report.sessionId} +
+ Page: {report.pageUrl} +
+
+ Strategy usage: +
+ {Object.entries(report.strategyUsage).map(([name, count]) => ( +
+ {name} + {count}x +
+ ))} + {Object.keys(report.strategyUsage).length === 0 && ( +
+ No strategy data yet. Run an extraction. +
+ )} +
+ )} + + {activeTab === 'metrics' && !report && ( +
+ No session data. Navigate to instagram.com/saved and click Start Extraction. +
+ )} + + {activeTab === 'failures' && ( +
+ {report && report.failures.length > 0 ? ( + report.failures.map((f, i) => ) + ) : ( +
+ No failures recorded ✓ +
+ )} +
+ )} + + {activeTab === 'log' && ( +
+ {events.length === 0 ? ( +
+ No events yet. +
+ ) : ( + events.map((e, i) => ( +
+ {e.ts} + {e.stage} +
+                    {JSON.stringify(e.payload, null, 2)}
+                  
+
+ )) + )} +
+ )} +
); }; diff --git a/docs/verification/alpha-report.md b/docs/verification/alpha-report.md new file mode 100644 index 0000000..ac6e9e2 --- /dev/null +++ b/docs/verification/alpha-report.md @@ -0,0 +1,177 @@ +# Alpha Stabilization Report — Sprint 3 + +> **Status**: PENDING LIVE VALIDATION +> +> This report template is generated by the engineering platform. Quantitative rows will +> be replaced with real data after executing the extension against a live Instagram +> Saved collection. The instrumentation infrastructure is in place and ready. + +## How to Generate This Report + +1. Run `pnpm run build` inside `apps/extension` +2. Load `apps/extension/dist` as an unpacked extension in Chrome +3. Navigate to `https://www.instagram.com/saved` +4. Click **Start Extraction** in the popup +5. Scroll through the saved collection until the feed ends +6. Click **Export JSON** — this downloads the full `ISessionReport` +7. Replace the placeholder values below with data from the export + +--- + +## Session Summary + +| Field | Value | +| :--------- | :-------------------------------- | +| Session ID | _(from export)_ | +| Page URL | `https://www.instagram.com/saved` | +| Started At | _(from export)_ | +| Ended At | _(from export)_ | +| Heap Usage | _(MB — from export)_ | + +--- + +## Extraction Metrics + +| Metric | Count | Notes | +| :-------------------------------- | :---: | :---------------------------------------------------------- | +| **Discovered** | — | Resources found by `DiscoveryEngine` via `MutationObserver` | +| **Extracted** | — | Resources successfully normalized into `IResource` | +| **Duplicates** | — | Resources skipped by fingerprint deduplication | +| **Skipped** | — | Resources skipped by feature flags | +| **Failed** | — | Resources that produced an `IFailureRecord` | +| **Extraction time (total ms)** | — | Wall-clock time in content script extraction | +| **Normalization time (total ms)** | — | Wall-clock time in `InstagramNormalizer` | +| **Average extraction time (ms)** | — | `extractionTimeMs / extracted` | +| **Success rate** | — | `extracted / discovered * 100` % | + +--- + +## Strategy Usage + +| Strategy | Invocations | Notes | +| :---------------------------- | :---------: | :----------------------------- | +| `SemanticArticleStrategy` | — | Primary path | +| `DataAttributeStrategy` | — | Fallback 1 | +| `StructuralHeuristicStrategy` | — | Fallback 2 (lowest confidence) | + +--- + +## Failure Analysis + +> Failures are automatically classified into four categories by the Background Worker. +> Each failure emits an `IFailureRecord` containing a trimmed DOM snapshot. + +### Summary + +| Category | Count | % of Failures | +| :---------------------- | :---: | :-----------: | +| `selector_failure` | — | — | +| `parsing_failure` | — | — | +| `normalization_failure` | — | — | +| `network_error` | — | — | +| `unknown` | — | — | + +--- + +### Known Failure Modes (Pre-Alpha Hypotheses) + +These are anticipated based on static analysis of the Instagram DOM. Each must be confirmed or +refuted with real-world evidence after the live run. + +--- + +#### FM-001: Dynamic class name obfuscation + +- **Category**: `selector_failure` +- **Root cause**: Instagram uses Webpack-generated class names that rotate on deployments. + The `SemanticArticleStrategy` relies on stable ARIA roles and `href` patterns, not class names, + but the `DataAttributeStrategy` fallback may attempt to query class-based attributes that no + longer exist. +- **DOM Snapshot**: _(attach from live run)_ +- **Proposed fix**: Remove all class-name selectors from strategies. Rely exclusively on ARIA roles, + `href` patterns, `time[datetime]`, and element tag names. +- **Regression test**: `connectors/instagram/tests/fixtures/obfuscated-classes.html` +- **Status**: Hypothesis — requires live confirmation + +--- + +#### FM-002: Infinite scroll boundary — last element not discovered + +- **Category**: `selector_failure` +- **Root cause**: When the Instagram feed reaches the end, the `MutationObserver` may fire a final + mutation that removes rather than adds articles, causing the last batch to be missed. +- **DOM Snapshot**: _(attach from live run)_ +- **Proposed fix**: Add a final `scanDOM(document.body)` call when the observer detects no more + addedNodes after a 2-second idle period. +- **Regression test**: `connectors/instagram/tests/fixtures/feed-end.html` +- **Status**: Hypothesis — requires live confirmation + +--- + +#### FM-003: Protected content — login-gated media + +- **Category**: `network_error` +- **Root cause**: CDN media URLs embedded in `` attributes may expire or return 403 + for non-authenticated requests when accessed outside the page context. +- **Proposed fix**: Record the source URI at extraction time and flag it as `localUri: undefined`. + Do not attempt to fetch the URI during extraction. Deferral to the hydration phase is correct. +- **Regression test**: N/A (the domain model already handles `localUri: undefined`) +- **Status**: Hypothesis — requires live confirmation + +--- + +#### FM-004: Carousel pagination — only first slide captured + +- **Category**: `parsing_failure` +- **Root cause**: Instagram renders carousel slides lazily. Only the first slide's `` is + present in the DOM on initial load; subsequent slides are injected on swipe/click. +- **DOM Snapshot**: _(attach from live run)_ +- **Proposed fix**: After detecting a carousel via the dot-indicator heuristic, dispatch a + synthetic click on the next-slide button in the content script, wait 300ms for the DOM mutation, + and re-scan. Repeat until no next button is present. +- **Regression test**: `connectors/instagram/tests/fixtures/carousel-lazy-slides.html` +- **Status**: Hypothesis — requires live confirmation + +--- + +#### FM-005: Reel video URI missing — video not yet buffered + +- **Category**: `parsing_failure` +- **Root cause**: Reel `